Suppose I have a matrices C1,C2 as follows:
C1 = nx2 cell each cell is [5x5 double].
C2 = 1x1 cell contain a [5x5 double].
How to calculate C3 as:
C3{1,1} = C1{1,1}+C2{1,1};
C3{1,2} = C1{1,2}+C2{1,1};
.
.
C3{n,2} = C1{n,2}+C2{1,1};
using cellfun or any other method without looping
For cases like those when you have regular sized arrays, you should be preferably using multi-dimensional arrays rather than slow cell arrays. Sticking with the cell arrays though, here's one vectorized solution using bsxfun as the basis of vectorized broadcasted summations after converting them to multi-dimensional arrays -
%// Store size of each cell and size of C1 for later reshaping purposes
[m,n] = size(C1{1,1})
[nr,nc] = size(C1);
%// Perform broadcasted summations with BSXFUN
sums = bsxfun(#plus,cat(3,C1{:}),C2{1,1})
%// Reshape and convert back to cell arrays as desired output
out = reshape(mat2cell(sums,m,n,ones(1,nr*nc)),nr,nc)
A straightforward use of cellfun does exactly what you want:
C3 = cellfun(#(x) x+C2{1,1},C1,'uniformoutput',false);
This will essentially loop over each element of the cell array C1, and for each element apply the anonymous function #(x) x+C2{1,1}, i.e. each element will be added to C2{1,1}. The resulting elements are returned in a cell array of the same size as C1.
For a few smaller test cases I compared this solution to that suggested by #Divakar. The result is not trivial, since both cellfun and cat (used in Divakar's solution) are (in)famously slow. I threw in a third version to check, in which I defined a temporary variable in my anonymous function:
tmpvar=C2{1,1};
C3a2=cellfun(#(x) x+tmpvar,C1,'uniformoutput',false);
The rationale behind this is that accessing that single cell element should have some overhead, and I'm unsure whether the entire cell is pulled into the workspace of the anonymous function.
I defined a separate function to test the three cases in order to let JIT do its job (but note that I'm using R2012b, a newer version could give quite different results, with the new execution engine and everything). I ran all three cases on the same random input (with a C2 cell array of size [1,1] and containing an array of the same size as C1{k,l}), choosing the shortest runtime from 10 attempts (based on tic/toc).
5x5 cell array of 10x10 matrices:
cellfun: 0.000452 s
cellfun+tmpvar: 0.000287 s
bsxfun(cat): 0.002970 s
5x5 cell array of 100x100 matrices:
cellfun: 0.000988 s
cellfun+tmpvar: 0.000963 s
bsxfun(cat): 0.004661 s
10x10 cell array of 5x5 matrices:
cellfun: 0.001580 s
cellfun+tmpvar: 0.000945 s
bsxfun(cat): 0.011358 s
100x100 cell array of 5x5 matrices:
cellfun: 0.108276 s
cellfun+tmpvar: 0.082675 s
bsxfun(cat): 1.132417 s
Based on these small test cases I'm tempted to conclude that
Using a temporary variable in the anonymous function given to cellfun can indeed count if the larger cell array is large, which makes sense (since then the function is evaluated a larger number of times).
The bsxfun(cat)-based solution is a bit slower for small cell arrays, and much slower for larger cell arrays. I suspect that cat is to blame: it takes a lot for cat to put the extra dimension together. I could even imagine that using a loop with preallocation might outperform cat.
It would be interesting to check the same for the new execution engine, and on much larger (n>1000) matrices and cell arrays.
Related
I have generated a cell array of 1x5 cells with a 10x1 column vector on each cell.
How can I find the average of all the column vectors? So to have a final 10x1 new column vector that contains the means. Thank you
Here is an easy solution:
mean([A{:}]) % column-wise mean (1x5)
mean([A{:}],2) % row-wise mean (10x1)
I would concatenate the cell array contents along the second dimension (using cat and {:} indexing to get a comma separated list) and then take the mean along this first dimension
result = mean(cat(2, data{:}));
Since your data is purely numeric, you should avoid cell arrays and instead deal with a 5 x 10 matrix as that will be much more performant. You can easily create that the same way we did above.
matrix_data = cat(2, data{:});
MATLAB question:
I have an array A(2,2,2) that is three-dimensional. I would like to define a 2x2 array as a subarray of A, as follows:
B = A(1,:,:).
That is, we are simply projecting on the first component. But matlab will now treat this 2x2 matrix as a 1x2x2 array instead, so that I can't do certain things (like multiply by another 2x2 matrix).
How do I get B as a 2x2 subarray of A?
If you think about a skyscraper, your A(1,:,:) is taking the first floor out and this operation inevitably happens across the 3rd dimension.
You can use reshape(), squeeze() or permute() to get rid of the singleton dimension:
reshape(A(1,:,:),2,2)
squeeze(A(1,:,:))
permute(A(1,:,:),[2,3,1])
squeeze() pretty much does all the job by itself, however it is not an inbuilt function and in fact uses reshape(). The other two alternatives are expected to be faster.
You'd want to use the function squeeze which removes the singleton dimensions:
B = squeeze(A(1,:,:))
I have to create a very big 3D matrix (such as: 500000x60x60). Is there any way to do this in matlab?
When I try
omega = zeros(500000,60,60,'single');
I get an out-of-memory error.
The sparse function is no option since it is only meant for 2D matrices. So is there any alternative to that for higher dimensional matrices?
Matlab only has support for sparse matrices (2D). For 3D tensors/arrays, you'll have to use a workaround. I can think of two:
linear indexing
cell arrays
Linear indexing
You can create a sparse vector like so:
A = spalloc(500000*60*60, 1, 100);
where the last entry (100) refers to the amount of non-zeros eventually to be assigned to A. If you know this amount beforehand it makes memory usage for A more efficient. If you don't know it beforehand just use some number close to it, it'll still work, but A can consume more memory in the end than it strictly needs to.
Then you can refer to elements as if it is a 3D array like so:
A(sub2ind(size(A), i,j,k))
where i, j and k are the indices to the 1st, 2nd and 3rd dimension, respectively.
Cell arrays
Create each 2D page in the 3D tensor/array as a cell array:
a = cellfun(#(x) spalloc(500000, 60, 100), cell(60,1), 'UniformOutput', false);
The same story goes for this last entry into spalloc. Then concatenate in 3D like so:
A = cat(3, a{:});
then you can refer to individual elements like so:
A{i,j,k}
where i, j and k are the indices to the 1st, 2nd and 3rd dimension, respectively.
Since your matrix is sparse, try to use ndsparse (N-dimensional sparse arrays FEX)
I have a single row matrix theta in Matlab with a couple hundred values; I would like to create a vector for each value in theta. Preferably I can simply store these values in a list so I can take dot products of individual elements in the list lator; how would I go about doing this?
For now, the code I have is
arrayfun(#(x) [sin(x),0,cos(x)],thetas,'UniformOutput',false);
which generates a bunch of [1x3 double]'s.
Instead of creating a cell array, you can also just create a numeric array of size numberOfThetas-by-3, like so:
A = [sin(thetas);zeros(size(thetas));cos(thetas)]'; %'# make n-by-3 by transposing
To calculate the dot product between any two vectors i and j, you can write
dotProduct = sum(A(i,:).*A(j,:));
You don't have to unnecessarily construct for loops to re-build the matrix as suggested by strictlyrude27. There is a nice inbuilt function cell2mat that does this for you in a single line.
Say your A is a 100 element cell, each of which holds a 1x3 vector. If you wanted to collect them such that each cell of A is a separate row, the command is simply
matrixA = cell2mat(A(:));
The output to your code is a cell array, whose elements are the 1x3 vectors you wanted. So suppose you assigned A = arrayfun(#(x) [sin(x),0,cos(x)],thetas,'UniformOutput',false); as you have up there. The vector corresponding with the ith element of array thetas may be accessed with A{i}. At this point you could use a for loop to construct a matrix whose ith column is the vector corresponding to the ith element of thetas.
Two questions:
1) I've found a piece of code that says something like cellArr{x}{y}{3,8} = 1.0;, I was wondering what the {3,8} means. The program connections various nodes in a collections of connected graphs together. Here we would say that "in the set of graphs x, the graph y's connection from 3 to 8 has a vertex label of 1.0". Still, in general what does the syntax {3,8} mean in MatLab?
2) This probably isn't the place for this question but should I really be using cell arrays if I know I'm always going to be having vertex values i.e. decimals/floats. Would a matrix be better because I know I'm only going to have a single data type?
Thank you :).
Cell arrays can have multiple dimensions, and thus they can be indexed with multiple subscripts like any other multidimensional array. The syntax {3,8} is indexing a (presumably) 2-D cell array, getting the contents of the cell in the third row and eighth column.
There are two main reasons to use cell arrays: storing data of different types or storing data of different sizes. Assuming x and y are scalar indices in your example, then cellArr is a cell array with the cell indexed by x containing another cell array, whose cell indexed by y contains a 2-D cell array which stores your vertex labels.
Now, if your vertex labels are all the same data type and are all just single non-empty (i.e. not []) values, then the 2-D cell array at the lowest level could be turned into a 2-D numeric array, and your indexing will look like this:
cellArr{x}{y}(3,8) = 1.0; %# Note the use of () instead of {}
The question now becomes how to handle the two enclosing sets of cell arrays indexed by x and y. If every cell that can be indexed by y contains 2-D numeric arrays all of the same size and type, then that cell array could be turned into a 3-D numeric array that could be indexed like so:
cellArr{x}(3,8,y) = 1.0; %# Here I've chosen to use y as the third dimension
Finally, if every cell that can be indexed by x contains 3-D numeric arrays that are again all of the same size and type, then cellArr could be turned into a 4-D numeric array that could be indexed like so:
numArr(3,8,y,x) = 1.0;
You could change the order of the subscripts (i.e. the dimensions of numArr) to your liking, but I put x and y at the end so that if you were to index a subarray of vertex labels like numArr(:,:,y,x) it will return it as a 2-D array. If you had the indices ordered such that you would index a subarray of vertex labels like numArr(x,y,:,:), it will return the result as a 4-D array with ones for the two leading singleton dimensions (which you would have to remove using functions like SQUEEZE).
The syntax {3,8} are cell array indices just as the {x} and {y} are. So cellArr is a cell vector of cell vectors. One of these cell vectors is indexed by {x}. This cell vector is itself a vector of cell 2d-matrices which is indexed by {y}. Finally, this cell matrix is indexed by {3,8}, i.e. the 3rd row and 8th column.
If all of your data is numeric then you'd be far better off using a 4 dimensional array. For your example, this array would be indexed by numericArray[x, y, 3, 8].