Suppose we have logical image y and we want to make a copy of it. What is differences between the following statements:
x = y;
x = y==1;
x = y is an assignment. It sets the variable x to the value currently contained in variable y.
x==y is a logical operator asking "Is x equal to y"?
The statement x=y==1 sets all parts of x to true where the corresponding value of y is equal to 1.
The difference between the two statements you pose is thus that in the first statement, x=y, x becomes an exact copy of y. In the second statement however, x becomes a logical matrix with boolean values. 1 where y contains a 1 and 0 where y contains anything but 1.
In your specific case, where y already is a logical matrix (thus containing only 1 and 0) both statements are thus equivalent as per the above and then the first statement will be faster as the equality check is redundant and thus adds unnecessary overhead.
Related
I have two column arrays x and y with matching numbers, but the first few numbers in y are missing. How can I index the rows where the numbers are missing in x?
For example, if I have
x = [1,5,6,5,8,8,10]'
y = [6,5,8,8,10]'
it should return:
z = 0,0,1,1,1,1,1
(where z is the same size as x)
If the array is only missing numbers at the beginning using the NaN (Not a Number) term can be used to pad the array. After padding the array to equal sizes a comparison operation across the corresponding indices/elements respectively can be done. This in short will pad the array and then check if the corresponding elements match.
x = [1,5,6,5,8,8,10]';
y = [6,5,8,8,10]';
Length_Difference = length(x) - length(y);
Padding_Vector = NaN(1,Length_Difference).';
y = [Padding_Vector; y];
Matches = (x == y);
Matches.'
But if you're simply trying to see if the individual elements of x exist in y using ismember() will do the trick. To check for the opposite case use ismember(y,x).
Matches = ismember(x,y);
Matches.'
Ran using MATLAB R2019b
I have inequalities with two unknown variables. So how could I assume one variable with different values and get the others?
For instance: -15<10*x+2*y<20.
How could I assume x=2, 3, and so on, and then find answer of (y) depending on the value of (x)?
I have been trying to apply the assume and find commands, but unfortunately, I could not. So I hope anyone could help me, please.
Looking forward to hearing from you.
I am new to Matlab, so I have been trying to apply solve, assume, and find commands
clear all;
clc;
syms x y real;
z=solve(-15<10*x+2*y,[x y])
b=solve(10*x+2*y<20,[x y])
yinterval = [ z,b]
I expect the output: to assume x=different numbers and then y= be a list of possible results depending on the value of x
Thanks,
For each value of x, technically there are infinite values of y that satisfy those equations, so for my solution, I assumed x and y were integer values. As well, it appears that you want to give the program a set of x values and have it calculate y values for each x value. Instead of using the solve command, we can simply use a couple of loops to find all satisfactory integer values of y for each value of x.
To start, we need to make a results matrix to store each x,y pair that satisfies the equations you've given. This is called pre-allocation, as we're pre-allocating the space needed to store our answers. Using the equations, we can deduce that there will be 17 satisfactory y values per x. So, our first two lines of code will be initializing the desired x-values and the results matrix:
xVec = 1:5; %x-vector, change this to whatever x-values you want to test
results = zeros(length(xVec)*14, 2); %results matrix
Note: If you decide to iterate x or y by a value different than +1 (more on that later), you'll need to come up with a different method of creating this results matrix. You could also just not pre-allocate the results matrix, but your code will run slower as the size of the results matrix will be changing on each loop.
Next are the loops. Admittedly, this is not the most elegant solution, but it'll get the job done. First, we need an index to keep up with where we are in our results matrix. This is pretty easy, we'll just call it index and start at 1 (since MATLAB indexes from 1 in matrices. Remember that!):
index = 1; %index for results matrix
Next, we need to loop through each value in our x-vector. Simply use a for loop:
for x = xVec
...
For each value of x, there is a minimum value of y. This value can be solved for in
-15 < 10*x + 2*y --> -14 = 10*x + 2*y_min
So, simply solving for y gives us our next line of code:
y = -7 - 5*x; %solving for y
Note: each time we iterate x in our for loop, a new starting value of y will be calculated.
Finally, we need to loop through values of y that still satisfy the inequalities given. This is performed through use of a while loop:
while 10*x + 2*y > -15 && 10*x + 2*y < 20
...
Note: && is the 'and' statement while using loops. You can't use a single equation for this (i.e. you can't say something like -15 < x < 20, you have to split them up using &&).
Since we solved for the first value of y, we can go ahead and record the current x and y values in our results matrix:
results(index, :) = [x, y]; %storing current x- and y-values
Then, we need to iterate y, as otherwise we'd be stuck in this while-loop forever.
y = y + 1;
Note: You can iterate this y-value with whatever amount you want. I chose to iterate by 1 each time, as I assumed you wanted to find integer values. Just change the +1 to whatever value you want.
Finally, we iterate our index, so that the next pair of x,y values that satisfy our equations don't overwrite our previous solutions.
index = index + 1;
All that's left is to close our loops and run! As I said, this isn't the most efficient solution, so I wouldn't use this for large amounts of x- and y-values. As well, like with iterating the y-values, the x-values can have any 'step-size' you want. As it's coded currently, it jumps +1 between each x, but changing the xVec input to any vector will still work (ex. xVec = 1:0.1:5; iterates the x-value by +0.1 each step instead of +1).
Here's the code all together, sans comments (since I wrote the comments while making the above code snippets):
xVec = 1:5;
results = zeros(length(xVec)*14, 2);
index = 1;
for x = xVec
y = -7 - 5*x;
while 10*x + 2*y > -15 && 10*x + 2*y < 20
results(index, :) = [x, y];
y = y + 1;
index = index + 1;
end
end
Let me know if you have any questions!
In Matlab R2010a:
I am familiar with finding values based on criteria as well as finding the first value in a vector that satisfies criteria. However, how does one find X's and not Y's in the following example? In this case, X's are the first values of a group of values that are findable given my criteria, and there are multiple groups like this amidst thousands of junk values.
I have an vector with 10,000 or more values. Let J be junk values, while X and Y are both values my find criteria will pick up. X's are interesting to me because they are the 'first' values of a series of values that satisfy my criteria before becoming J's. Assume that there are hundreds or thousands more J's in between the X's and Y's, but here is a small example
[J,J,J,J,J,J,J,J,J,J,J,X,Y,Y,Y,Y,J,J,J,J,J,J,J,J,J,X,Y,Y,Y,Y,J];
Assuming that you're not doing something to strange with those Xs and Ys, this is quite easy. You just need to find the beginning of each cluster:
% Create data using your example (Y can equal X, but we make it different)
J = 1; X = 2; Y = 3;
A = [J,J,J,J,J,J,J,J,J,J,J,X,Y,Y,Y,Y,J,J,J,J,J,J,J,J,J,X,Y,Y,Y,Y,J];
a0 = (A==X); % Logical indices of A that match X condition
start = find([a0(1) diff(a0)]==1) % Start index of each group beginning with X
vals = A(start) % Should all be equal to X
which returns
start =
12 26
vals =
2 2
The J values don't even need to be all the same, just not equal to what ever you're detecting as X. You might also find my answer to this similar question helpful.
A = [J,J,J,J,J,J,J,J,J,J,J,X,Y,Y,Y,Y,J,J,J,J,J,J,J,J,J,X,Y,Y,Y,Y,J]; % created vector
I = A(A~=J); % separated out all values that are not junk
V = I(I==I(1)); % separated all values that match the first non-junk value
This question already has answers here:
Is there a Matlab conditional IF operator that can be placed INLINE like VBA's IIF
(10 answers)
Closed 9 years ago.
I'm looking for Matlab equivalent of c# condition ? true-expression : false-expression conditional assignment. The most I know of is a = 5>2, which is true\false assignment,
but is there any one line conditional assignment for
if condition a=1;else a=2; end?
For numeric arrays, there is another solution --
// C:
A = COND ? X : Y;
becomes
% MATLAB
% A, X and Y are numerics
% COND is a logical condition.
A = COND.*X + (~COND).*Y ;
Advantage:
works wonderfully in parallel for vectors or large arrays - each item in A gets assigned depending on the corresponding condition. The same line works for:
condition is scalar, arrays X and Y are equal in size
condition is an array of any size, X and Y are scalars
condition and X and Y are all arrays of the same size
Warning:
Doesn't work gracefully with NaNs. Beware! If an element of X is nan, or an element of Y is nan, then you'll get a NaN in A, irrespective of the condition.
Really Useful corollary:
you can use bsxfun where COND and X/Y have different sizes.
A = bsxfun( #times, COND', X ) + bsxfun( #times, ~COND', Y );
works for example where COND and X/Y are vectors of different lengths.
neat eh?
One line conditional assignment:
a(a > 5) = 2;
This is an example of logical indexing, a > 5 is a logical (i.e. Boolean or binary) matrix/array the same size as a with a 1 where ever the expression was true. The left side of the above assignment refers to all the positions in a where a>5 has a 1.
b = a > 5; % if a = [9,3,5,6], b = [1,0,0,1]
a(~b) = 3;
c = a > 10;
a(b&c) = ...
Etc...you can do pretty much anything you'd expect with such logical arrays.
Matlab does not have a ternary operator. You though easily write a function that will do such thing for you:
function c = conditional(condition , a , b)
if condition
c = a;
else
c = b;
end
end
I have a mesh grid defined as
[X, Y, Z] = meshgrid(-100:100, -100:100, 25); % z will have more values later
and two shapes (ovals, in this case):
x_offset_1 = 40;
x_offset_2 = -x_offset_1;
o1 = ((X-x_offset_1).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
o2 = ((X-x_offset_2).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
Now, I want to find all points that are nonzero in either oval. I tried
union = o1+o2;
but since I simply add them, the overlapping region will have a value of 2 instead of the desired 1.
How can I set all nonzero entries in the matrix to 1, regardless of their previous value?
(I tried normalized_union = union./union;, but then I end up with NaN in all 0 elements because I'm dividing by zero...)
Simplest solution: A=A~=0;, where A is your matrix.
This just performs a logical operation that checks if each element is zero. So it returns 1 if the element is non-zero and 0 if it is zero.
First suggestion: don't use union as a variable name, since that will shadow the built-in function union. I'd suggest using the variable name inEitherOval instead since it's more descriptive...
Now, one option you have is to do something like what abcd suggests in which you add your matrices o1 and o2 and use the relational not equal to operator:
inEitherOval = (o1+o2) ~= 0;
A couple of other possibilities in the same vein use the logical not operator or the function logical:
inEitherOval = ~~(o1+o2); % Double negation
inEitherOval = logical(o1+o2); % Convert to logical type
However, the most succinct solution is to apply the logical or operator directly to o1 and o2:
inEitherOval = o1|o2;
Which will result in a value of 1 where either matrix is non-zero and zero otherwise.
There is another simple solution, A=logical(A)