This question already has answers here:
Difference between [] and [1x0] in MATLAB
(4 answers)
Closed 7 years ago.
In many cases I have seen that MATLAB would return empty objects and if you look at their size, they would be something like 1 x 0 or0 x 1.
An example is the following piece of code :
img = zeros(256); % Create a square zero image of dimension 256 X 256
regions = detectMSERFeatures(img);
size(regions)
If you look at the size of regions, it will by 0 X 1. My questions are the following. Some of these questions can be overlapping.
What is the meaning of such dimensions ?
What can be said about the memory layout of such objects ? The reason I am asking about memory layout is because MATLAB allows you to write the following statement: temp = zeros(1,0);
Why can't MATLAB simply return an empty constant like NULL in such cases instead of returning weirdoes of size 1 x 0 ?
Arrays in MATLAB can have any of their dimensions of size zero - I guess that may seem odd initially, but they're just arrays like any other.
You can create them directly:
>> a = double.empty(2,0,3,0,2)
a =
Empty array: 2-by-0-by-3-by-0-by-2
or using other array creation functions such as zeros, ones, rand and so on.
Note that, as is obvious from the above, empty arrays still have a class - you can create them with double.empty, uint8.empty, logical.empty and so on. The same is also true for user-defined classes.
It's very useful to have such arrays, rather than just a NULL element. Without them, you would need to spend a lot of programming effort to check for edge cases where you had a NULL rather than an array, and you wouldn't be able to distinguish between arrays that were NULL because they had no rows, and arrays that were NULL because they had no columns.
In addition, they're useful for initializing arrays. For example, let's say you have an array that needs to start empty but get filled later, and you know that it's always going to have three rows but a variable number of columns. You can then initialize it as double.empty(3,0), and you know that your initial value will always pass any checks on the number of rows your array has. That wouldn't work if you initialized it to [] (which is zero by zero), or to a NULL element.
Finally, you can also multiply them in the same way as non-empty arrays. It may be surprising to you that:
>> a = double.empty(2,0)
a =
Empty matrix: 2-by-0
>> b = double.empty(0,3)
b =
Empty matrix: 0-by-3
>> a*b
ans =
0 0 0
0 0 0
but if you think it through, it's just a logical and necessary application/extension of the regular rules for matrix multiplication.
As to how they're stored in memory - again, they're stored just like regular MATLAB arrays. I can't recall the exact details (look in the documentation for mxArray), but it's basically a header giving the dimensions (some of which may be zero), followed by a list of the elements in column-major order (which in this case is an empty list).
Related
I've come across some unexpected behaviour in matlab that I can't make sense of when performing vectorised assignment:
>> q=4;
>> q(q==[1,3,4,5,7,8])
The logical indices contain a true value outside of the array bounds.
>> q(q==[1,3,4,5,7,8])=1
q =
4 0 1
Why does the command q(q==[1,3,4,5,7,8]) result in an error, but the command q(q==[1,3,4,5,7,8])=1 work? And how does it arrive at 4 0 1 being the output?
The difference between q(i) and q(i)=a is that the former must produce the value of an array element; if i is out of bounds, MATLAB chooses to give an error rather than invent a value (good choice IMO). And the latter must write a value to an array element; if i is out of bounds, MATLAB chooses to extend the array so that it is large enough to be able to write to that location (this has also proven to be a good choice, it is useful and used extensively in code). Numeric arrays are extended by adding zeros.
In your specific case, q==[1,3,4,5,7,8] is the logical array [0,0,1,0,0,0]. This means that you are trying to index i=3. Since q has a single value, reading at index 3 is out of bounds, but we can write there. q is padded to size 3 by adding zeros, and then the value 1 is written to the third element.
The following error occurs quite frequently:
Subscript indices must either be real positive integers or logicals
I have found many questions about this but not one with a really generic answer. Hence I would like to have the general solution for dealing with this problem.
Subscript indices must either be real positive integers or logicals
In nearly all cases this error is caused by one of two reasons. Fortunately there is an easy check for this.
First of all make sure you are at the line where the error occurs, this can usually be achieved by using dbstop if error before you run your function or script. Now we can check for the first problem:
1. Somewhere an invalid index is used to access a variable
Find every variable, and see how they are being indexed. A variable being indexed is typically in one of these forms:
variableName(index,index)
variableName{index,index}
variableName{indices}(indices)
Now simply look at the stuff between the brackets, and select every index. Then hit f9 to evaluate the result and check whether it is a real positive integer or logical. Visual inspection is usually sufficient (remember that acceptable values are in true,false or 1,2,3,... BUT NOT 0) , but for a large matrix you can use things like isequal(index, round(index)), or more exactly isequal(x, max(1,round(abs(x)))) to check for real positive integers. To check the class you can use class(index) which should return 'logical' if the values are all 'true' or 'false'.
Make sure to check evaluate every index, even those that look unusual as per the example below. If all indices check out, you are probably facing the second problem:
2. A function name has been overshadowed by a user defined variable
MATLAB functions often have very intuitive names. This is convenient, but sometimes results in accidentally overloading (builtin) functions, i.e. creating a variable with the same name as a function for example you could go max = 9 and for the rest of you script/function Matlab will consider max to be a variable instead of the function max so you will get this error if you try something like max([1 8 0 3 7]) because instead of return the maximum value of that vector, Matlab now assumes you are trying to index the variable max and 0 is an invalid index.
In order to check which variables you have you can look at the workspace. However if you are looking for a systematic approach here is one:
For every letter or word that is followed by brackets () and has not been confirmed to have proper indices in step 1. Check whether it is actually a variable. This can easily be done by using which.
Examples
Simple occurrence of invalid index
a = 1;
b = 2;
c = 3;
a(b/c)
Here we will evaluate b/c and find that it is not a nicely rounded number.
Complicated occurrence of invalid index
a = 1;
b = 2;
c = 3;
d = 1:10;
a(b+mean(d(cell2mat({b}):c)))
I recommend working inside out. So first evaluate the most inner variable being indexed: d. It turns out that cell2mat({b}):c, nicely evaluates to integers. Then evaluate b+mean(d(cell2mat({b}):c)) and find that we don't have an integer or logical as index to a.
Here we will evaluate b/c and find that it is not a nicely rounded number.
Overloaded a function
which mean
% some directory\filename.m
You should see something like this to actually confirm that something is a function.
a = 1:4;
b=0:0.1:1;
mean(a) = 2.5;
mean(b);
Here we see that mean has accidentally been assigned to. Now we get:
which mean
% mean is a variable.
In Matlab (and most other programming languages) the multiplication sign must always be written. While in your math class you probably learned that you can write write a(a+a) instead of a*(a+a), this is not the same in matlab. The first is an indexing or function call, while the second is a multiplication.
>> a=0
a =
0
>> a*(a+a)
ans =
0
>> a(a+a)
Subscript indices must either be real
positive integers or logicals.
Answers to this question so far focused on the sources of this error, which is great. But it is important to understand the powerful yet very intuitive feature of matrix indexing in Matlab. Hence how indexing works and what is a valid index would help avoid this error in the first place by using valid indices.
At its core, given an array A of length n, there are two ways of indexing it.
Linear indexing: with subset of integers from 1 : n (duplicates allowed). 0 is not allowed, as Matlab arrays are 1-based, unless you use the method below. For higher-dimensional arrays, multiple subscripts are internally converted into a linear index, although in an efficient and transparent manner.
Logical indexing:wherein you use a n-length array of 0s and 1s, to pick those elements where indexing is true. In this case, unique(index) must have only 0 and 1.
So a valid indexing array into another array with n number of elements ca be:
entirely logical of the same size, or
linear with subsets of integers from 1:n
Keeping this in mind, invalid indexing error occurs when you mix the two types of indexing: one or more zeros occur in your linearly indexing array, or you mix 0s and 1s with anything other than 0s and 1s :)
There is tons of material online to learn this including this one:
http://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html
The following error occurs quite frequently:
Subscript indices must either be real positive integers or logicals
I have found many questions about this but not one with a really generic answer. Hence I would like to have the general solution for dealing with this problem.
Subscript indices must either be real positive integers or logicals
In nearly all cases this error is caused by one of two reasons. Fortunately there is an easy check for this.
First of all make sure you are at the line where the error occurs, this can usually be achieved by using dbstop if error before you run your function or script. Now we can check for the first problem:
1. Somewhere an invalid index is used to access a variable
Find every variable, and see how they are being indexed. A variable being indexed is typically in one of these forms:
variableName(index,index)
variableName{index,index}
variableName{indices}(indices)
Now simply look at the stuff between the brackets, and select every index. Then hit f9 to evaluate the result and check whether it is a real positive integer or logical. Visual inspection is usually sufficient (remember that acceptable values are in true,false or 1,2,3,... BUT NOT 0) , but for a large matrix you can use things like isequal(index, round(index)), or more exactly isequal(x, max(1,round(abs(x)))) to check for real positive integers. To check the class you can use class(index) which should return 'logical' if the values are all 'true' or 'false'.
Make sure to check evaluate every index, even those that look unusual as per the example below. If all indices check out, you are probably facing the second problem:
2. A function name has been overshadowed by a user defined variable
MATLAB functions often have very intuitive names. This is convenient, but sometimes results in accidentally overloading (builtin) functions, i.e. creating a variable with the same name as a function for example you could go max = 9 and for the rest of you script/function Matlab will consider max to be a variable instead of the function max so you will get this error if you try something like max([1 8 0 3 7]) because instead of return the maximum value of that vector, Matlab now assumes you are trying to index the variable max and 0 is an invalid index.
In order to check which variables you have you can look at the workspace. However if you are looking for a systematic approach here is one:
For every letter or word that is followed by brackets () and has not been confirmed to have proper indices in step 1. Check whether it is actually a variable. This can easily be done by using which.
Examples
Simple occurrence of invalid index
a = 1;
b = 2;
c = 3;
a(b/c)
Here we will evaluate b/c and find that it is not a nicely rounded number.
Complicated occurrence of invalid index
a = 1;
b = 2;
c = 3;
d = 1:10;
a(b+mean(d(cell2mat({b}):c)))
I recommend working inside out. So first evaluate the most inner variable being indexed: d. It turns out that cell2mat({b}):c, nicely evaluates to integers. Then evaluate b+mean(d(cell2mat({b}):c)) and find that we don't have an integer or logical as index to a.
Here we will evaluate b/c and find that it is not a nicely rounded number.
Overloaded a function
which mean
% some directory\filename.m
You should see something like this to actually confirm that something is a function.
a = 1:4;
b=0:0.1:1;
mean(a) = 2.5;
mean(b);
Here we see that mean has accidentally been assigned to. Now we get:
which mean
% mean is a variable.
In Matlab (and most other programming languages) the multiplication sign must always be written. While in your math class you probably learned that you can write write a(a+a) instead of a*(a+a), this is not the same in matlab. The first is an indexing or function call, while the second is a multiplication.
>> a=0
a =
0
>> a*(a+a)
ans =
0
>> a(a+a)
Subscript indices must either be real
positive integers or logicals.
Answers to this question so far focused on the sources of this error, which is great. But it is important to understand the powerful yet very intuitive feature of matrix indexing in Matlab. Hence how indexing works and what is a valid index would help avoid this error in the first place by using valid indices.
At its core, given an array A of length n, there are two ways of indexing it.
Linear indexing: with subset of integers from 1 : n (duplicates allowed). 0 is not allowed, as Matlab arrays are 1-based, unless you use the method below. For higher-dimensional arrays, multiple subscripts are internally converted into a linear index, although in an efficient and transparent manner.
Logical indexing:wherein you use a n-length array of 0s and 1s, to pick those elements where indexing is true. In this case, unique(index) must have only 0 and 1.
So a valid indexing array into another array with n number of elements ca be:
entirely logical of the same size, or
linear with subsets of integers from 1:n
Keeping this in mind, invalid indexing error occurs when you mix the two types of indexing: one or more zeros occur in your linearly indexing array, or you mix 0s and 1s with anything other than 0s and 1s :)
There is tons of material online to learn this including this one:
http://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html
This question already has an answer here:
Operands to the || and && operators must be convertible to logical scalar values
(1 answer)
Closed 9 years ago.
I have a vector containing a list of data (X and Y coords) which i want to compare to an array of 100 vectors (each with similar but not the same XY Coords) in order to find a match.
Each vector ranges in data size (between 10 and 20 cords) which causes issues when matching matrices of different sizes.
so in order to match i have used the matchfeatures which matches exact data which is no use as vectors different sizes.
so i made
(using pdist to turn cords into distances)
threshigh = (vector1/100) * 110;
threslow = (vector1/100) * 90;
if (Vector2 <= threshigh)&&(vector2 >= threslow)
disp its a match
else
not a match
end
this is perfect! but.. I cannot use operators on vectors as they only apply to scalar quantities.
how do i get around this?
it has also occurred to me even if this works and some values in the vector fall between this range it will not match unless they all do? how do i just take majority of results?
The link of the duplicate question should solve your first problem. As for your second issue:
... even if this works and some values in the vector fall between this range it will not match unless they all do? how do i just take majority of results?
Once you have a logical array (with 1's at the positions corresponding to elements that fall within the specified range, and 0's elsewhere), you can manipulate it to your liking.
In its current form, the if statement branches only if all elements are true (logical '1'). If you know that the tested expression might be a vector (that is, an array), you can do the following:
Use the any command to check if at least one element in the array is true:
if any(...)
%// Do something...
end
Use the all command to check if all elements are true:
if all(...)
%// Do something...
end
(using all here is superfluous, but it does enhance readability...)
Check for a majority of '1's by using mode:
if mode(double(...))
%// Do something...
end
mode returns the most frequent element in the array, so if it's '1' the if statement will branch.
I need to convert this to Matlab code, and am struggling without the "table" function.
Table[{i,1000,ability,savingsrate,0,RandomInteger[{15,30}],1,0},{i,nrhhs}];
So basically, these values are all just numbers, and I think I need to use a function handle, or maybe a for loop. I'm no expert, so I really need some help?
I'm not an expert in Mathematics (just used it long time ago). According to this documentation for Table function, you are using this form:
Table[expr, {i, imax}]
generates a list of the values of expr when i runs from 1 to imax.
It looks like your statement will produce list duplicating the list in first argument increasing i from 1 to nrhhs and using different random number.
In MATLAB the output can be equivalent to a matrix or a cell array.
To create a matrix with rows as your lists you can do:
result = [ (1:nrhhs)', repmat([1000,ability,savingsrate,0],nrhhs,1), ...
randi([15 30],nrhhs,1), repmat([1,0],nrhhs,1) ];
You can convert the above matrix to a cell array:
resultcell = cell2mat(result, ones(nrhhs,1));
The "Table" example you gave creates a list of nrhhs sub-lists, each of which contains 8 numbers (i, 1000, ability, savingsrate, 0, a random integer between 15 and 30 inclusive, 1, and 0). This is essentially (though not exactly) the same as an nrhhs x 8 matrix.
Assuming you do just want a matrix out, though, an analogous for loop in Matlab would be:
result = zeros(nrhhs,8); % preallocate memory for the result
for i = 1:nrhhs
result(i,:) = [i 1000 ability savingsrate 0 randi([15 30]) 1 0];
end
This method is likely slower than yuk's answer (which makes much more efficient use of vectors to avoid the for loop), but might be a little easier to pick apart depending on how familiar you are with Matlab.