I have a loop in MATLAB that fills a cell array in my workspace (2011b, Windows 7, 64 bit) with the following entries:
my_array =
[1x219 uint16]
[ 138]
[1x0 uint16] <---- row #3
[1x2 uint16]
[1x0 uint16]
[] <---- row #6
[ 210]
[1x7 uint16]
[1x0 uint16]
[1x4 uint16]
[1x0 uint16]
[ 280]
[]
[]
[ 293]
[ 295]
[1x2 uint16]
[ 298]
[1x0 uint16]
[1x8 uint16]
[1x5 uint16]
Note that some entries hold [], as in row #6, while others hold [1x0] items, as in row #3.
Is there any difference between them? (other than the fact that MATLAB displays them differently). Any differences in how MATLAB represents them in memory?
If the difference is only about how MATLAB internally represents them, why should the programmer be aware of this difference ? (i.e. why display them differently?). Is it a (harmless) bug? or is there any benefit in knowing that such arrays are represented differently?
In most cases (see below for an exception) there is no real difference. Both are considered "empty", since at least one dimension has a size of 0. However, I wouldn't call this a bug, since as a programmer you may want to see this information in some cases.
Say, for example, you have a 2-D matrix and you want to index some rows and some columns to extract into a smaller matrix:
>> M = magic(4) %# Create a 4-by-4 matrix
M =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> rowIndex = [1 3]; %# A set of row indices
>> columnIndex = []; %# A set of column indices, which happen to be empty
>> subM = M(rowIndex,columnIndex)
subM =
Empty matrix: 2-by-0
Note that the empty result still tells you some information, specifically that you tried to index 2 rows from the original matrix. If the result just showed [], you wouldn't know if it was empty because your row indices were empty, or your column indices were empty, or both.
The Caveat...
There are some cases when an empty matrix defined as [] (i.e. all of its dimensions are 0) may give you different results than an empty matrix that still has some non-zero dimensions. For example, matrix multiplication can give you different (and somewhat non-intuitive) results when dealing with different kinds of empty matrices. Let's consider these 3 empty matrices:
>> a = zeros(1,0); %# A 1-by-0 empty matrix
>> b = zeros(0,1); %# A 0-by-1 empty matrix
>> c = []; %# A 0-by-0 empty matrix
Now, let's try multiplying these together in different ways:
>> b*a
ans =
[] %# We get a 0-by-0 empty matrix. OK, makes sense.
>> a*b
ans =
0 %# We get a 1-by-1 matrix of zeroes! Wah?!
>> a*c
ans =
Empty matrix: 1-by-0 %# We get back the same empty matrix as a.
>> c*b
ans =
Empty matrix: 0-by-1 %# We get back the same empty matrix as b.
>> b*c
??? Error using ==> mtimes
Inner matrix dimensions must agree. %# The second dimension of the first
%# argument has to match the first
%# dimension of the second argument
%# when multiplying matrices.
Getting a non-empty matrix by multiplying two empty matrices is probably enough to make your head hurt, but it kinda makes sense since the result still doesn't really contain anything (i.e. it has a value of 0).
When concatenating matrices, the common dimension has to match.
It's not currently an error if it doesn't match when one of the operands is empty, but you do get a nasty warning that future versions might be more strict.
Examples:
>> [ones(1,2);zeros(0,9)]
Warning: Concatenation involves an empty array with an incorrect number of columns.
This may not be allowed in a future release.
ans =
1 1
>> [ones(2,1),zeros(9,0)]
Warning: Concatenation involves an empty array with an incorrect number of rows.
This may not be allowed in a future release.
ans =
1
1
Another difference is in the internal representation of both versions of empty. Especially when it comes to bundle together objects of the same class in an array.
Say you have a dummy class:
classdef A < handle
%A Summary of this class goes here
% Detailed explanation goes here
properties
end
methods
end
end
If you try to start an array from empty and grow it into an array of A objects:
clear all
clc
% Try to use the default [] for an array of A objects.
my_array = [];
my_array(1) = A;
Then you get:
??? The following error occurred converting from A to double:
Error using ==> double
Conversion to double from A is not possible.
Error in ==> main2 at 6
my_array(1) = A;
But if you do:
% Now try to use the class dependent empty for an array of A objects.
my_array = A.empty;
my_array(1) = A;
Then all is fine.
I hope this adds to the explanations given before.
If concatenation and multiplication is not enough to worry about, there is still looping. Here are two ways to observe the difference:
1. Loop over the variable size
for t = 1:size(zeros(0,0),1); % Or simply []
'no'
end
for t = 1:size(zeros(1,0),1); % Or zeros(0,1)
'yes'
end
Will print 'yes', if you replace size by length it will not print anything at all.
If this is not a surprise, perhaps the next one will be.
2. Iterating an empty matrix using a for loop
for t = [] %// Iterate an empty 0x0 matrix
1
end
for t = ones(1, 0) %// Iterate an empty 1x0 matrix
2
end
for t = ones(0, 1) %// Iterate an empty 0x1 matrix
3
end
Will print:
ans =
3
To conclude with a concise answer to both of your questions:
Yes there is definitely a difference between them
Indeed I believe the programmer will benefit from being aware of this difference as the difference may produce unexpected results
Related
A sparse matrix is a large matrix with almost all elements of the same
value (typically zero). The normal representation of a sparse matrix
takes up lots of memory when the useful information can be captured
with much less. A possible way to represent a sparse matrix is with a
cell vector whose first element is a 2-element vector representing the
size of the sparse matrix. The second element is a scalar specifying
the default value of the sparse matrix. Each successive element of the
cell vector is a 3-element vector representing one element of the
sparse matrix that has a value other than the default. The three
elements are the row index, the column index and the actual value.
Write a function called "sparse2matrix" that takes a single input of a
cell vector as defined above and returns the output argument called
"matrix", the matrix in its traditional form. Consider the following
run:
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
matrix = sparse2matrix(cellvec)
matrix =
0 3 0
0 -3 0
Good morning/afternoon/night, everyone
I was wondering if you could help me with this.
I am trying to complete this, but I am not sure how to deal with this. I understand that I am interested in the first part of the cell vector, but I am not sure about how to tell Matlab I need that. This is my code:
function matrix = sparse2matrix(x)
A = [2 3];
B = 0;
C = [1, 2, 3];
x = {A, 0, C};
matrix = cell2mat(x);
end
The result of this code is different from the result I showed above.
I am not getting the right answer and honestly I do not know what to do, so I would appreciate if you guide me a little bit.
Not the most elegant way of doing it but it gets the job done. Uses the cell2mat() function and indexing to grab the necessary values for each step. A for-loop is then used to obtain the 3-element vectors that is used to change the array values from the default values in the respective indices.
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
[matrix] = sparse2matrix(cellvec)
function [matrix] = sparse2matrix(x)
Matrix_Size = cell2mat(x(1,1));
Matrix_Height = Matrix_Size(1);
Matrix_Width = Matrix_Size(2);
Default_Value = cell2mat(x(1,2));
matrix = Default_Value*ones(Matrix_Height,Matrix_Width);
Triplets = x(3:end);
Number_Of_Triplets = length(Triplets);
for Triplet_Index = 1: Number_Of_Triplets
Current_Triplet = cell2mat(Triplets(1,Triplet_Index));
Row = Current_Triplet(1,1);
Column = Current_Triplet(1,2);
Value = Current_Triplet(1,3);
matrix(Row,Column) = Value;
end
end
Explanation:
The first line in the local function sparse2matrix() indicates to retrieve row 1, column 1 of the cell array x and then convert it to a matrix. The conversion is done using the cell2mat() function.
Matrix_Size = cell2mat(x(1,1));
Results in:
Matrix_Size = [2 3]
The following line indicates to grab index 1 of the previous array Matrix_Size. This will be used to determine the height of the output array matrix. This is done in a similar fashion to evaluate the Matrix_Width using index 2.
Matrix_Height = Matrix_Size(1);
Results in:
Matrix_Height = 2
Ran using MATLAB R2019b
In Matlab, is there a way to concatenate a non-scalar structure without losing the empty fields? This is interfering with my ability to index within the structure.
I would prefer not to populate all of my "y" fields with NaN for memory management reasons, but I can do this if it is the only work around.
"code" is always fully populated and has no empty cells. "y" could be fully populated but usually is not.
I am providing a quick example: simplified structure (it is really tens of thousands of entries with 50+ fields)
% create example structure
x = struct('y',{1 [] 3 4},'code', {{'a'}, {'b'}, {'c'}, {'b'}});
% concatenate
out = [x.y];
% find indices with code 'b'
ind = find(strcmpi([x.code], 'b'));
% desired output
outSub = out(ind)
I would expect out to yield:
out = [1 NaN 3 4]
Instead I get:
out = [1 3 4]
When trying to use code to create an index to find the values in out that match the desired code value, this obviously does not work.
Error: Index exceeds the number of array elements (3).
The desired output would yield:
out = [2 4];
outSub = [NaN 4]
I am fully open to indexing in a different way as well.
Using the comment above, here is the final solution:
% create example structure
x = struct('y',{1 [] 3 4},'code', {{'a'}, {'b'}, {'c'}, {'b'}});
% concatenate
out = {x.y};
% find indices with code 'b'
ind = find(strcmpi([x.code], 'b'));
% desired output - cell array
outSubCell = out(ind);
% substitute [] for NaN
outSubCell(cellfun('isempty',outSubCell)) = {NaN};
% convert output to double array
outSub = cell2mat(outSubCell)
I have the following problem:
A = [] % matrix
Q = [] % number on non zero in each row
for i=1:10
% I generate a path with name path
% add the path to the matrix A
end
% count number on non zero numbers in each row
How can I do that?
Here is an illustrative example:
If the path in first iteration was: path = [ 1 2 3 4 ]
In the second iteration: path = [ 4 5 6 ]
In third iteration: path = [ 7 2 ]
Then A should be like this:
A =
[1 2 3 4 ,
4 5 6 0 ,
7 2 0 0 ]
After, I would like a vector to show me the number of numbers different than zero in each row like so:
Q = [4 3 2]
Given your comments, this is what I would suggest that you do:
Because the actual paths are not known a priori, I would suggest that you store all of the paths in a cell array. Given your for loop condition, I'm assuming that there will be 10 paths. The actual paths we don't know, but we know there will be 10.
Write some code that will figure out the maximum length of path as this will dictate the size of our matrix A.
Create the matrix A then store of all the paths in, with zeroes appended at the end of each path should they not be the size of the maximum length of the path.
Using the matrix A, figure out how many non-zeroes there are.
Without any further ado, here is the code you are seeking. With each step, I will explain what I am doing to get the desired step.
Step #1
pathCellArray = cell(10, 1);
for i = 1 : 10
%// Insert path generation code here...
%// Assume that the variable is called
%// 'path' that stores this path
%//..
pathCellArray{i} = path;
end
This should be self-explanatory. For each path that you generate, store it in its corresponding cell. The reason why we are placing each path in a cell is because the length of each path is variable. We are also doing this so we can figure out how many columns we need to allocate for A. Also take note that I am creating a cell array of columns. The reason why is because when we do a reconstruction and solve for A, it will make things easier.
Step #2
%// Use cellfun that takes in a cell array and we will
%// generate an array as output that contains the
%// size of each path. We will find the maximum of
%// all of these that will dictate our size of A
lengthArray = cellfun(#length, pathCellArray);
numCols = max(lengthArray);
Now this is something cool. You probably have never seen cellfun before. How cellfun works is that we specify a custom function, and cellfun will apply this function to every element to this cell. For the output of cellfun the i'th position of the output is the output of the custom function for each i'th position of the input cell array. As such, what we are doing here is that we are generating a length array (stored as lengthArray) that goes through each cell and figures out how big the path is. lengthArray will thus store how long each path is. Once we do that, we figure out what the longest path is so we know how big A will be.
Step #3
pathCellArrayAppend = cellfun(#(x) [x zeros(1,numCols-length(x))], ...
pathCellArray, 'UniformOutput', false);
A = cell2mat(pathCellArrayAppend);
This code is probably the most complex out of all that you have dealt with. What I am basically doing here is taking that cell array of paths that I created, and generating a new cell array where each element in the cell (which is our path) gets appended with zeroes up until the length of the longest path. If you look, the custom function we have generated basically creates the array that first stores the path that we want, then zero-pads the rest of the array with zeroes. We have to specify UniformOutput to false as because the output of the the custom function is no longer a single value. It is an array as the output, which is why this flag is set to false. The output of this call to cellfun will generate 10 cell arrays where each element is a path and is zero-padded with zeroes. We then call cell2mat to convert this cell array back to matrix form, and A is your result.
Step #4
Q = cellfun(#(x) sum(x ~= 0), pathCellArrayAppend);
We thus call cellfun again. This time we take a look at our cell array that has all of the paths that are zero-padded. We go through each cell, and count how many non-zero entries there are. Q will store this result. Note that we don't need to set UniformOutput to false as the output of the custom function is a single number.
Using your example that you have provided, here is how the code will look with their corresponding outputs:
%// Step #1 - Simulated
p1 = [1 2 3 4];
p2 = [4 5 6];
p3 = [7 2];
pathCellArray = {p1; p2; p3};
%// Step #2
lengthArray = cellfun(#length, pathCellArray)
>> lengthArray =
4
3
2
numCols = max(lengthArray)
>> numCols =
4
%// Step #3
pathCellArrayAppend = cellfun(#(x) [x zeros(1,numCols-length(x))], ...
pathCellArray, 'UniformOutput', false);
A = cell2mat(pathCellArrayAppend)
>> A =
1 2 3 4
4 5 6 0
7 2 0 0
%// Step #4
Q = cellfun(#(x) sum(x ~= 0), pathCellArrayAppend)
>> Q =
4
3
2
NB: You could simply use Step #2 as your Q, provided that your paths are non-zero. If there are, then you need to go right to Step #4.
I've noticed various cases in Matlab and octave where functions accept both matrices and vectors, but doesn't do the same thing with vectors as it does with matrices.
This can be frustrating because when you input a matrix with a variable number of rows/columns, it could be interpreted as a vector and do something you don't expect when the height/width is 1 making for difficult debugging and weird conditional edge cases.
I'll list a few I've found, but I'm curious what others people have run into
(Note: I'm only looking for cases where code accepts matrices as valid input. Anything that raises an exception when a non-vector matrix is given as an argument doesn't count)
1) "diag" can be used to mean diagonal of a matrix or turn a vector into a diagonal matrix
Since the former is generally only used for square matrices this isn't so egregious in matlab, but in Octave it can be particularly painful when Octave interperets a vector beginning with a nonzero element and everything else zeros as a "diagonal matrix" ie
t=eye(3);
size(diag(t(:,3))) == [3,3]
size(diag(t(:,2))) == [3,3]
size(diag(t(:,1))) == [1,1]
2) Indexing into a row-vector with logicals returns a row-vector
Indexing into anything else with logicals returns a column vector
a = 1:3;
b = true(1,3);
size(a(b)) == [1, 3]
a = [a; a];
b = [b; b];
size(a(b)) == [6, 1]
3) Indexing into a vector v with an index vector i returns a vector of the same (row/col) type as v. But if either v or i is a matrix, the return value has the same size as i.
a = 1:3;
b = a';
size(a(b)) == [1, 3]
b = [b,b];
size(a(b)) == [3, 2]
4) max, min, sum etc. operate on the columns of a matrix M individiually unless M is 1xn in which case they operate on M as a single row-vector
a = 1:3
size(max(a)) == [1, 1]
a = [a;a]
size(max(a)) == [1, 3]
max is particularly bad since it can't even take a dimension as an argument (unlike sum)
What other such cases should I watch out for when writing octave/matlab code?
Each language has its own concepts. An important point of this language is to very often think of matrices as an array of vectors, each column an entry. Things will start to make sense then. If you don't want that behavior, use matrix(:) as the argument to those functions which will pass a single vector, rather than a matrix. For example:
octave> a = magic (5);
octave> max (a)
ans =
23 24 25 21 22
octave> max (a(:))
ans = 25
1) This is not true with at least Octave 3.6.4. I'm not 100% sure but may be related related to this bug which has already been fixed.
2) If you index with boolean values, it will considered to be a mask and treated as such. If you index with non-boolean values, then it's treated as the indexes for the values. This makes perfect sense to me.
3) This is not true. The returned has always the same size of the index, independent if it's a matrix or vector. The only exception is that if the index is a vector, the output will be a single row. The idea is that indexing with a single vector/matrix returns something of the same size:
octave> a = 4:7
a =
4 5 6 7
octave> a([1 1])
ans =
4 4
octave> a([1 3])
ans =
4 6
octave> a([1 3; 3 1])
ans =
4 6
6 4
4) max does take dimension as argument at least in Octave. From the 3.6.4 help text of max:
For a vector argument, return the maximum value. For a matrix
argument, return the maximum value from each column, as a row vector,
or over the dimension DIM if defined, in which case Y should be set to
the empty matrix (it's ignored otherwise).
The rest applies like I said on the intro. If you supply a matrix, it will think of each column as a dataset.
1) As pointed out by the other user, this is not true with at Octave >= 3.6.4.
In case 2) the rule is for vectors, return always the same shape of vector, for anything else return a column vector, consider:
>> a = reshape (1:3, 1,1,3)
a(:,:,1) =
1.0000e+000
a(:,:,2) =
2.0000e+000
a(:,:,3) =
3.0000e+000
>> b = true(1,3)
b =
1×3 logical array
1 1 1
>> a(b)
ans(:,:,1) =
1.0000e+000
ans(:,:,2) =
2.0000e+000
ans(:,:,3) =
3.0000e+000
>> a = [a;a]
a(:,:,1) =
1.0000e+000
1.0000e+000
a(:,:,2) =
2.0000e+000
2.0000e+000
a(:,:,3) =
3.0000e+000
3.0000e+000
>> b = [b;b]
b =
2×3 logical array
1 1 1
1 1 1
>> a(b)
ans =
1.0000e+000
1.0000e+000
2.0000e+000
2.0000e+000
3.0000e+000
3.0000e+000
You can see that this makes sense since vectors have a clear 'direction' but other shaped matrices do not when you remove elements. EDIT: actually I just checked and Octave doesn't seem work this way exactly, but probably should.
3) This is consistent with 2). Essentially if you supply a list of indices the direction of the indexed vector is preserved. If you supply indices with a shape like a matrix, the new information is the index matrix shape is used. This is more flexible, since you can always do a(b(:)) to preserve the shape of a if you so wish. You may say it is not consistent, but remember indexing with logicals may reduce the number of elements to be returned, so they cannot be reshaped in this way.
4) As pointed out in a comment, you can specify dimension for max/min to operate on: min(rand(3),[],1) or max(rand(3),[],2), but in this case there are 'legacy' issues with these functions which data back to when they were first created and now are very difficult to change without upsetting people.
I have created a sparse matrix using MEX and also created a sparse matrix using MATLAB. To fill in the values of the matrix i have used same formula.
Now to check if the both the matrices are equal I used result=(A==B). result returns 1 for all indices, which implies that all the matrix elements are equal.
But if I do find(A-B) it returns some indices, which indicates that at these indices the values are non-zero. How is this possible?
Note: When i compare the value at these indices it shows equal !
I'm guessing you have values of infinity cropping up in your matrices at the same points. For example:
>> A = Inf;
>> B = Inf;
>> A == B
ans =
1 %# They are treated as equal...
>> A-B
ans =
NaN %# ...but their difference actually results in NaN...
>> find(A-B)
ans =
1 %# ...which is treated as a non-zero value.
The discrepancy here results from the fact that certain operations involving infinity result in NaN values. You can check to see if you have any infinities in A and B by using the function ISINF like so:
any(isinf(A(:)))
any(isinf(B(:)))
And if you get a value of 1 (i.e. true), then the presence of infinities is likely the source of your discrepancy.