I'm new to Matlab and I'm just stuck with this line of code:
[r,c] = find(abs(fh) <= 2 );
Beware: ironically it was easy for me understanding what the right part of the assignment is.
The left part however (which is maybe the definition of a variable)... I don't know how to search because I have too generic results by googling just square brackets with something inside.
My assumption is this line of code is creating some a matrix with r rows and c columns but r and c are nowhere to be found in the rest of the code.... or maybe it's a simple array with two elements... but it doesn't make much sense to me honestly.
Can you guys help me please?
Whenever you see that syntax, it means that the function being called is returning more than one output argument (two in this case).
The best way to learn about the function output arguments is to check the documentation:
https://www.mathworks.com/help/matlab/ref/find.html#d120e368337
[row,col] = find(___) returns the row and column subscripts of each
nonzero element in array X using any of the input arguments in
previous syntaxes.
The output arguments are positional, so r is row, c is col.
Take a look in Matlab find() docs.
If X is a vector, then find returns a vector with the same orientation as X.
If X is a multidimensional array, then find returns a column vector of the linear indices of the result.
If X contains no nonzero elements or is empty, then find returns an empty array.
If you call
X = [18 3 1 11;
8 10 11 3;
9 14 6 1;
4 3 15 21 ]
[row,col] = find(X>0 & X<10,3)
You will get:
row = 3×1
2
3
4
col = 3×1
1
1
1
Which represents the index (row number and column number) of each elements that satifies the condition you defined. Since it returns more than 1 value, you can divide the output in two different variables and that is what the left side represents.
Related
I have a 2 dimensional array L, and I am trying to create a vector of linear indices ind for each row of this array.
L=
1 5 25 4 0 0
2 3 3 45 5 6
45 5 6 0 0 0
I am using lenr to store the number of non zero elements in each row (starting from column 1).
lenr=
4
6
3
Then I have 1x45 array RULES. Indices stored in L refer to elements in RULES. Since I want to vectorize the code, I decided to create linear indices and then run RULES(ind).
This works perfectly:
ind=sub2ind(size(L),1,lenr(1));
while this doesn't work:
ind=sub2ind(size(L),1:3,1:lenr(1:3));
Any ideas?
UPDATE:
This is what I initially tried to vectorize the code, but it did not works and that's why I checked linear indices:
rul=repmat(RULES,3);
result = rul((L(1:J,1:lenr(1:J))));
If I correctly interpret your edit, you want to create a variable result that contains the elements of RULES indicated by the non-zero elements of L. Note that in general, the best way to vectorize sub2ind is to not use sub2ind.
If you want result to be a linear array, you can simply write
%// transpose so that result is ordered by row
L_transposed = L.';
result = RULES(L_transposed(L_transposed>0));
If, instead, you want result to be an array of the same size as L, with all numbers in L replaced by the corresponding element in RULES, it's even simpler:
result = L;
result(result>0) = RULES(result>0);
I need to create a function that has the input argument n, a integer , n>1 , and an output argument v, which is a column vector of length n containing all the positive integers smaller than or equal to n, arranged in such a way that no element of the vector equals its own index.
I know how to define the function
This is what I tried so far but it doesn't work
function[v]=int_col(n)
[1,n] = size(n);
k=1:n;
v=n(1:n);
v=k'
end
Let's take a look at what you have:
[1,n] = size(n);
This line doesn't make a lot of sense: n is an integer, which means that size(n) will give you [1,1], you don't need that. (Also an expression like [1,n] can't be on the left hand side of an assignment.) Drop that line. It's useless.
k=1:n;
That line is pretty good, k is now a row vector of size n containing the integers from 1 to n.
v=n(1:n);
Doesn't make sense. n isn't a vector (or you can say it's a 1x1 vector) either way, indexing into it (that's what the parentheses do) doesn't make sense. Drop that line too.
v=k'
That's also a nice line. It makes a column vector v out of your row vector k. The only thing that this doesn't satisfy is the "arranged in such a way that no element of the vector equals its own index" part, since right now every element equals its own index. So now you need to find a way to either shift those elements or shuffle them around in some way that satisfies this condition and you'd be done.
Let's give a working solution. You should really look into it and see how this thing works. It's important to solve the problem in smaller steps and to know what the code is doing.
function [v] = int_col(n)
if n <= 1
error('argument must be >1')
end
v = 1:n; % generate a row-vector of 1 to n
v = v'; % make it a column vector
v = circshift(v,1); % shift all elements by 1
end
This is the result:
>> int_col(5)
ans =
5
1
2
3
4
Instead of using circshift you can do the following as well:
v = [v(end);v(1:end-1)];
We can specify a list by a = [1:3]
but at the same time,
we can also specify a list by a = 1:3.
I see that the output on the command window for a is the same, i.e.
a =
1 2 3
But is there any difference in the internal structure where we cannot see and cause difference in further calculation?
I don't think so. In MATLAB, the square brackets can be used for concatenating some number of matrices together. So for example, I could do
x = [1:2, 5:7, 9:12]
x =
1 2 5 6 7 9 10 11 12
In your case, you are doing matrix concatenation with only one matrix, which simply yields the matrix provided.
You don't even need to go to vectors. Even for scalars, the following are equivalent:
a = 123;
a = [ 123 ];
The first one declares a as the scalar 123, while the second one declares it as a length-1 vector whose sole element is 123. In MATLAB, these two are exactly the same thing.
Here's an example (using octave):
octave:1> x = 123
x = 123
octave:2> x(2) = 456
x =
123 456
As you can see, what was declared as a scalar could very easily be handled as a vector. I think everything is just stored as vectors.
I am new to matlab and I was wondering what it meant to use logical indexing/masking to extract data from a matrix.
I am trying to write a function that accepts a matrix and a user-inputted value to compute and display the total number of values in column 2 of the matrix that match with the user input.
The function itself should have no return value and will be called on later in another loop.
But besides all that hubbub, someone suggested that I use logical indexing/masking in this situation but never told me exactly what it was or how I could use it in my particular situation.
EDIT: since you updated the question, I am updating this answer a little.
Logical indexing is explained really well in this and this. In general, I doubt, if I can do a better job, given available time. However, I would try to connect your problem and logical indexing.
Lets declare an array A which has 2 columns. First column is index (as 1,2,3,...) and second column is its corresponding value, a random number.
A(:,1)=1:10;
A(:,2)=randi(5,[10 1]); //declares a 10x1 array and puts it into second column of A
userInputtedValue=3; //self-explanatory
You want to check what values in second column of A are equal to 3. Imagine as if you are making a query and MATLAB is giving you binary response, YES (1) or NO (0).
q=A(:,2)==3 //the query, what values in second column of A equal 3?
Now, for the indices where answer is YES, you want to extract the numbers in the first column of A. Then do some processing.
values=A(q,2); //only those elements will be extracted: 1. which lie in the
//second column of A AND where q takes value 1.
Now, if you want to count total number of values, just do:
numValues=length(values);
I hope now logical indexing is clear to you. However, do read the Mathworks posts which I have mentioned earlier.
I over simplified the code, and wrote more code than required in order to explain things. It can be achieved in a single-liner:
sum(mat(:,2)==userInputtedValue)
I'll give you an example that may illustrate what logical indexing is about:
array = [1 2 3 0 4 2];
array > 2
ans: [0 0 1 0 1 0]
using logical indexing you could filter elements that fullfil a certain condition
array(array>2) will give: [3 4]
you could also perform alterations to only those elements:
array(array>2) = 100;
array(array<=2) = 0;
will result in "array" equal to
[0 0 100 0 100 0]
Logical indexing means to have a logical / Boolean matrix that is the same size as the matrix that you are considering. You would use this as input into the matrix you're considering, and any locations that are true would be part of the output. Any locations that are false are not part of the output. To perform logical indexing, you would need to use logical / Boolean operators or conditions to facilitate the selection of elements in your matrix.
Let's concentrate on vectors as it's the easiest to deal with. Let's say we had the following vector:
>> A = 1:9
A =
1 2 3 4 5 6 7 8 9
Let's say I wanted to retrieve all values that are 5 or more. The logical condition for this would be A >= 5. We want to retrieve all values in A that are greater than or equal to 5. Therefore, if we did A >= 5, we get a logical vector which tells us which values in A satisfy the above condition:
>> A >= 5
ans =
0 0 0 0 1 1 1 1 1
This certainly tells us where in A the condition is satisfied. The last step would be to use this as input into A:
>> B = A(A >= 5)
B =
5 6 7 8 9
Cool! As you can see, there isn't a need for a for loop to help us select out elements that satisfy a condition. Let's go a step further. What if I want to find all even values of A? This would mean that if we divide by 2, the remainder would be zero, or mod(A,2) == 0. Let's extract out those elements:
>> C = A(mod(A,2) == 0)
C =
2 4 6 8
Nice! So let's go back to your question. Given your matrix A, let's extract out column 2.
>> col = A(:,2)
Now, we want to check to see if any of column #2 is equal to a certain value. Well we can generate a logical indexing array for that. Let's try with the value of 3:
>> ind = col == 3;
Now you'll have a logical vector that tells you which locations are equal to 3. If you want to determine how many are equal to 3, you just have to sum up the values:
>> s = sum(ind);
That's it! s contains how many values were equal to 3. Now, if you wanted to write a function that only displayed how many values were equal to some user defined input and displayed this event, you can do something like this:
function checkVal(A, val)
disp(sum(A(:,2) == val));
end
Quite simply, we extract the second column of A and see how many values are equal to val. This produces a logical array, and we simply sum up how many 1s there are. This would give you the total number of elements that are equal to val.
Troy Haskin pointed you to a very nice link that talks about logical indexing in more detail: http://www.mathworks.com/help/matlab/math/matrix-indexing.html?refresh=true#bq7eg38. Read that for more details on how to master logical indexing.
Good luck!
%% M is your Matrix
M = randi(10,4)
%% Val is the value that you are seeking to find
Val = 6
%% Col is the value of the matrix column that you wish to find it in
Col = 2
%% r is a vector that has zeros in all positions except when the Matrix value equals the user input it equals 1
r = M(:,Col)==Val
%% We can now sum all the non-zero values in r to get the number of matches
n = sum(r)
M =
4 2 2 5
3 6 7 1
4 4 1 6
5 8 7 8
Val =
6
Col =
2
r =
0
1
0
0
n =
1
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Over the years, reading others code, I encountered and collected some examples of MATLAB syntax which can be at first unusual and counterintuitive. Please, feel free to comment or complement this list. I verified it with r2006a.
MATLAB always returns first output argument of a function (if it has at least one) into its caller workspace, also unexpectedly if function is being called without returning arguments like myFunc1(); myFunc2(); the caller workspace still would contain first output of myFunc2(); as "invisible" ans variable. It could play an important role if ans is a reference object - it would remain alive.
set([], 'Background:Color','red')
MATLAB is very forgiving sometimes. In this case, setting properties to an array of objects works also with nonsense properties, at least when the array is empty. Such arrays usually come from harray = findobj(0,'Tag','NotExistingTag')
myArray([1,round(end/2)])
This use of end keyword may seem unclean but is sometimes very handy instead of using length(myArray).
any([]) ~= all([])
Surprisigly any([]) returns false and all([]) returns true. And I always thought that all is stronger then any.
EDIT:
with not empty argument all() returns true for a subset of values for which any() returns true (e.g. truth table). This means that any() false implies all() false. This simple rule is being violated by MATLAB with [] as argument.
Loren also blogged about it.
Select(Range(ExcelComObj))
Procedural style COM object method dispatch. Do not wonder that exist('Select') returns zero!
[myString, myCell]
MATLAB makes in this case an implicit cast of string variable myString to cell type {myString}. It works, also if I would not expect it to do so.
[double(1.8), uint8(123)] => 2 123
Another cast example. Everybody would probably expect uint8 value being cast to double but Mathworks have another opinion. Without a warning this behavior is very dangerous.
a = 5;
b = a();
It looks silly but you can call a variable with round brackets. Actually it makes sense because this way you can execute a function given its handle.
Syntax Foo(:) works not only on data but also with functions if called as Bar.Foo(:), in this scenario the function input argument is passed as char colon ':'.
For example let Bar.Foo = #(x) disp(x)
Now calling Bar.Foo(:) prints char ':' in the MATLAB Command Window.
This strange feature works with all MATLAB 7 versions without warnings.
a = {'aa', 'bb'
'cc', 'dd'};
Surprsisingly this code neither returns a vector nor rises an error but defins matrix, using just code layout. It is probably a relict from ancient times.
EDIT: very handy feature, see the comment by gnovice.
set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'})
This code does what you probably expect it to do. That function set accepts a struct as its second argument is a known fact and makes sense, and this sintax is just a cell2struct away.
Equvalence rules are sometimes unexpected at first. For example 'A'==65 returns true (although for C-experts it is self-evident). Similarly isequal([],{}) retuns, as expected, false and isequal([],'') returns true.
The string-numeric equivalence means that all string functions can be used also for numeric arrays, for example to find indices of a sub-array in a large array:
ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] )
MATLAB function isnumeric() returns false for booleans. This feels just ... false :-)
About which further unexpected/unusual MATLAB features are you aware?
Image coordinates vs plot coordinates Used to get me every time.
%# create an image with one white pixel
img = zeros(100);
img(25,65) = 1;
%# show the image
figure
imshow(img);
%# now circle the pixel. To be sure of the coordinate, let's run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it's not in the right place
%# plot a green circle with x,y switched, and it works
plot(y,x,'og')
Edit 1
Array dimensions
Variables have at least two dimensions. Scalars are size [1,1], vectors are size [1,n] or [n,1]. Thus, ndims returns 2 for any of them (in fact, ndims([]) is 2 as well, since size([]) is [0,0]). This makes it a bit cumbersome to test for the dimensionality of your input. To check for 1D arrays, you have to use isvector, 0D arrays need isscalar.
Edit 2
Array assignments
Normally, Matlab is strict with array assignments. For example
m = magic(3);
m(1:2,1:3) = zeros(3,2);
throws a
??? Subscripted assignment dimension mismatch.
However, these work:
m(1:2,1:2) = 1; %# scalar to vector
m(2,:) = ones(3,1); %# vector n-by-1 to vector 1-by-n (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'
Edit 3
Logical indexing with wrongly sized arrays Good luck debugging this!
Logical indexing seems to make a call to find, since your logical array doesn't need the same amount of elements as there are indices!
>> m = magic(4); %# a 4-by-4 array
>> id = logical([1 1 0 1 0])
id =
1 1 0 1 0
>> m(id,:) %# id has five elements, m only four rows
ans =
16 2 3 13
5 11 10 8
4 14 15 1
%# this wouldn't work if the last element of id was 1, btw
>> id = logical([1 1 0])
id =
1 1 0
>> m(id,:) %# id has three elements, m has four rows
ans =
16 2 3 13
5 11 10 8
Instead of listing examples of weird MATLAB syntax, I'll address some of the examples in the question that I think make sense or are expected/documented/desired behavior.
How ANY and ALL handle empty arguments:
The result of any([]) makes sense: there are no non-zero elements in the input vector (since it's empty), so it returns false.
The result of all([]) can be better understood by thinking about how you might implement your own version of this function:
function allAreTrue = my_all(inArray)
allAreTrue = true;
N = numel(inArray);
index = 1;
while allAreTrue && (index <= N)
allAreTrue = (inArray(index) ~= 0);
index = index + 1;
end
end
This function loops over the elements of inArray until it encounters one that is zero. If inArray is empty, the loop is never entered and the default value of allAreTrue is returned.
Concatenating unlike classes:
When concatenating different types into one array, MATLAB follows a preset precedence of classes and converts values accordingly. The general precedence order (from highest to lowest) is: char, integer (of any sign or number of bits), single, double, and logical. This is why [double(1.8), uint8(123)] gives you a result of type uint8. When combining unlike integer types (uint8, int32, etc.), the left-most matrix element determines the type of the result.
Multiple lines without using the line continuation operator (...):
When constructing a matrix with multiple rows, you can simply hit return after entering one row and enter the next row on the next line, without having to use a semicolon to define a new row or ... to continue the line. The following declarations are therefore equivalent:
a = {'aa', 'bb'
'cc', 'dd'};
a = {'aa', 'bb'; ...
'cc', 'dd'};
a = {'aa', 'bb'; 'cc', 'dd'};
Why would you want MATLAB to behave like this? One reason I've noticed is that it makes it easy to cut and paste data from, for example, an Excel document into a variable in the MATLAB command window. Try the following:
Select a region in an Excel file and copy it.
Type a = [ into MATLAB without hitting return.
Right-click on the MATLAB command window and select "Paste".
Type ]; and hit return. Now you have a variable a that contains the data from the rows and columns you selected in the Excel file, and which maintains the "shape" of the data.
Arrays vs. cells
Let's look at some basic syntax to start with. To create an array with elements a, b, c you write [a b c]. To create a cell with arrays A, B, C you write {A B C}. So far so good.
Accessing array elements is done like this: arr(i). For Cells, it's cell{i}. Still good.
Now let's try to delete an element. For arrays: arr(i) = []. Extrapolating from examples above, you might try cell{i} = {} for cells, but this is a syntax error. The correct syntax to delete an element of a cell is, in fact, the very same syntax you use for arrays: cell(i) = [].
So, most of the time you access cells using special syntax, but when deleting items you use the array syntax.
If you dig deeper you'll find that actually a cell is an array where each value is of a certain type. So you can still write cell(i), you'll just get {A} (a one-valued cell!) back. cell{i} is a shorthand to retrieve A directly.
All this is not very pretty IMO.