I have four 2*2 matrices called m1,m2,m3,m4. I want to create an empty 2*2 cell array which every element of it will be also 2*2 matrices. Then I want to put m1(1,1) & m2(1,1) & m3(1,1) & m4(1,1) elements into that created empty cell matrices so that element (1,1) of them will be that m1(1,1) & m2(1,1) & m3(1,1) & m4(1,1) s. And again do it again for next remaind elements as I said.
Can anyone help me do this with matlab?
You don't need anything crazy, just reshape and num2cell
c = reshape(num2cell([m1(:), m2(:), m3(:), m4(:)], 2), size(m1));
I think this is a good general way to do it.
Edit: 2015/07/25 14:45
Based on your comments it seems like what you have is a cell array
M = {m1, m2, ..., mn}
I think you're saying that each m is 2x2, but I'll assume it's qxr
And you want to get it in the form,
c = {[m1(1,1), m2(1,1), ..., mn(1,1)], [m1(1,2), m2(1,2), ..., mn(1,2)], ..., [m1(1,q), m1(1,q), ..., mn(1,q)]
[m1(2,1), m2(2,1), ..., mn(2,1)], [m1(2,2), m2(2,2), ..., mn(2,2)], ..., [m1(2,q), m1(2,q), ..., mn(2,q)]
...
[m1(r,1), m2(r,1), ..., mn(r,1)], [m1(r,2), m2(r,2), ..., mn(r,2)], ..., [m1(r,q), m1(r,q), ..., mn(r,q)]}
If all this is accurate, then the code you need is
c = reshape(num2cell(cell2mat(cellfun(#(m) m(:), M(:)', 'uni', 0)), 2), size(M{1}));
So a good way to test this is to make a M, then run the code
M = arrayfun(#(i) randi(100, 7, 3), 1:14, 'uni', 0);
c = reshape(num2cell(cell2mat(cellfun(#(m) m(:), M(:)', 'uni', 0)), 2), size(M{1}));
the only new piece compared to the above code is the cell2mat(cellfun(#(m) m(:), M(:)', 'uni', 0)). This takes M (which is a cell array of matrices) and first turns it into a cell array of column vectors (by the cellfun). It then concatenates those columns into a matrix which each row is a m1(i,j), m2(i,j), ... set. Then like before we split each row into its own cell of a cell array, then reshape it so it's the same size as one of the m's.
This seems to be a pure syntax problem.
c = cell(4,4); %Create the empty cell
c{1,1} = [m1(1,1) m2(1,1); m3(1,1) m4(1,1)]; Put a constructed 2x2 matrix in position 1,1
c{1,2} = [m1(1,2) m2(1,2); m3(1,2) m4(1,2)];
c{2,1} = [m1(2,1) m2(2,1); m3(2,1) m4(2,1)];
c{2,2} = [m1(2,2) m2(2,2); m3(2,2) m4(2,2)];
If you want, (e.g. if your actual problem is a much bigger size) you can do the same thing in loops. There may even be a clever arrayfun solution. But nothing will be faster.
Related
Lets say I have a structure like this:
S.index = 1:10;
S.testMatrix = zeros(3,3,10);
for x = 1:10
S.testMatrix(:,:,x) = magic(3) + x;
end
S.other = reshape(0:39, 4, 10);
It contains a 1x10 vector, a 3x3x10 multi-paged array and a 4x10 matrix. Now say I want to select only the entries corresponding to the indices between 2 and 8. mask = S.index > 2 & S.index < 8;
I tried structfun(#(x) x(mask), S, 'UniformOutput', 0); first which correctly worked for only the vector, which makes perfect sense. So then I figured all I needed to do was expand my mask. So I did this.
test = structfun(#(x) x(repmat(mask, size(x, ndims(x) - 1), 1)), S, 'UniformOutput',0);
The expanded mask was correct for the matrix but not the multi-paged array. And the 2D matrix was flattened to a vector.
If I was going to index these elements individually I would do something like this:
S2.index = S.index(mask);
S2.other = S.other(:,mask);
S2.testMatrix = S.testMatrix(:,:,mask);
My use case is for hundreds of structures each with 20+ fields. How do I script the indexing? The exact problem occurs is limited to a structure with 1xN vectors, 3xN and 4xN matrices and 3x3xN arrays. The mask is constructed based on one of the vectors representing time. The field names are constant for each structure so I could brute force the thing and type in the commands and run it as a function, but I'm looking for an intelligent way to index it.
Update: Here is something that looks promising.
fn = fieldnames(S);
for x = 1:length(fn)
extraDim = repmat({':'}, 1, ndims(S.(fn{x})) - 1);
S2.(fn{x}) = S.(fn{x})(extraDim{:}, mask);
end
You can exploit the fact that the string ':' can be used as an index instead of :, and build a comma-separated list of that string repeated the appropriate number of times for each field:
s = {':',':'}; % auxilary cell array to generate the comma-separated list
S2 = structfun(#(f) f(s{1:ndims(f)-1}, mask), S, 'UniformOutput', false);
Sorry about the bad title, I'm struggling to word this question well. Basically what I want to do is extract elements from a 2d matrix, from row by row, taking out a number of elements (N) starting at a particular column (k). In for loops, this would look like.
A = magic(6);
k = [2,2,3,3,4,4]; % for example
N = 3;
for j = 1:length(A)
B(j,:) = A(j,k(j):k(j)+N-1);
end
I figure there must be a neater way to do it than that.
You could use bsxfun to create an array of indices to use. Then combine this with the row numbers and pass it to sub2ind.
inds = sub2ind(size(A), repmat(1:size(A, 1), 3, 1), bsxfun(#plus, k, (0:(N-1))')).';
B = A(inds);
Or alternately without sub2ind (but slightly more cryptic).
B = A(bsxfun(#plus, 1:size(A,1), ((bsxfun(#plus, k, (0:(N-1)).')-1) * size(A,1))).');
Here's one approach using bsxfun's masking capability and thus logical indexing -
C = (1:size(A,2))';
At = A.';
B = reshape(At(bsxfun(#ge,C,k) & bsxfun(#lt,C,k+N)),N,[]).';
Say I have a nxm matrix and want to treat each row as vectors in a function. So, if I have a function that adds vectors, finds the Cartesian product of vectors or for some reason takes the input of several vectors, I want that function to treat each row in a matrix as a vector.
This sounds like a very operation in Matlab. You can access the ith row of a matrix A using A(i, :). For example, to add rows i and j, you would do A(i, :) + A(j, :).
Given an nxm matrix A:
If you want to edit a single column/row you could use the following syntax: A(:, i) for the ith-column and A(i, :) for ith-row.
If you want to edit from a column/row i to a column/row j, you could use that syntax: A(:, i:j) or A(i:j, :)
If you want to edit (i.e.) from the penultimate column/row to the last one, you could you: A(:, end-1:end) or A(end-1:end, :)
EDIT:
I can't add a comment above because I don't have 50 points, but you should post the function setprod. I think you should be able to do what you want to do, by iterating the matrix you're passing as an argument, with a for-next statement.
I think you're going to have to loop:
Input
M = [1 2;
3 4;
5 6];
Step 1: Generate a list of all possible row pairs (row index numbers)
n = size(M,1);
row_ind = nchoosek(1:n,2)
Step 2: Loop through these indices and generate the product set:
S{n,n} = []; //% Preallocation of cell matrix
for pair = 1:size(row_ind,1)
p1 = row_ind(pair,1);
p2 = row_ind(pair,2);
S{p1,p2} = setprod(M(p1,:), M(p2,:))
end
Transform the matrix into a list of row vectors using these two steps:
Convert the matrix into a cell array of the matrix rows, using mat2cell.
Generate a comma-separated list from the cell array, using linear indexing of the cell contents.
Example: let
v1 = [1 2];
v2 = [10 20];
v3 = [11 12];
M = [v1; v2; v3];
and let fun be a function that accepts an arbitrary number of vectors as its input. Then
C = mat2cell(M, ones(1,size(M,1)));
result = fun(C{:});
is the same as result = fun(v1, v2, v3).
I have a 1xN cell, call it X, whose components X{i} (for i in {1, 2, ..., N}) are either Mx1 cells of strings or Mx1 numeric vectors.
NOTE: the fact that X contains both text cells and numeric vectors precludes using cell2mat here:
>> tmp = cell2mat(X);
Error using cell2mat (line 46)
All contents of the input cell array must be of the same data type.
My question is:
What's MATLAB's "idiomatic" way to transpose this data into an array of M 1xN cells?
EDIT: To be clear, the data structure I want to arrive at, let's call it Y, is an M-long array of 1xN cells (each consisting of a mixture of numbers and strings). E.g., if N=2, and if X{1} is an Mx1 cell of strings, and X{2} is an Mx1 vector of doubles, then the desired data structure Y is such that, for any 1 ≤ i ≤ M, Y(i,:) is a 1x2 cell whose first element is the i-th string in X{1} and whose second element is the i-th double in X{2}. I.e. Y(i,:) would be the same as the 1x2 cell Yi defined as follows
xi1 = X(i, 1);
xi2 = X(i, 2);
Yi = {xi1{1} xi2{1}};
(Sorry for the awkwardness! I just can't find a MATLAB expression for Yi directly in terms X and i, without having to create intermediate variables xi1 and xi2.)
First of all, to my knowledge there is no 'idiomatic' way of doing that i Matlab. Remember, we're talking about a complex data structure with nested cells and differing types.
I tried to cook up a solution based on cellfun. It quickly got complicated and I didn't even succeed. So instead I would recommend doing a simple double for loop and a if like this:
for a=1:size(X,2),
for b=1:size(X{a},1),
if iscell(X{a}),
Y{a,b} = X{a}{b};
else
Y{a,b} = X{a}(b);
end
end
end
If X = {{'s1';'s2'} [3; 4]} then this solution will give Y = {'s1' 3 ;'s2' 4}.
As you see I have flattened the cell to one depth. To get your 1xN vectors, do Y{1,:}
Hope it helps
If each cell in X contains a vector of the same size convert it to a matrix, transpose that matrix and then convert it back to a cell array?
tmp = cell2mat(X);
Y = mat2cell(tmp', ...);
Here is the function:
feval(#(y) feval(#(x) cellfun(#(varargin)[varargin],x{:},'un',0), cellfun(#(x) feval(#(varargin) varargin{3-varargin{1}}(), iscell(x),x,num2cell(x)),y,'un',0)), {{'1','2','3'},[4 5 6],{7,8,9}})
Or stored as a function name:
transpose_nest = #(cell_nest) feval(#(y) feval(#(x) cellfun(#(varargin)[varargin],x{:},'un',0), cellfun(#(x) feval(#(varargin) varargin{3-varargin{1}}(),iscell(x),x,num2cell(x)),y,'un',0)), cell_nest);
transpose_nest({{'1','2','3'},[4 5 6],{7,8,9}})
{{'1',4,7},{'2',5,8},{'3',6,9}}
It is based on a Matlab equivalent of Scheme's (apply map list '(("1" "2" "3") (4 5 6) (7 8 9))) that only works on sub cells:
feval(#(x) cellfun(#(varargin)[varargin],x{:},'un',0), {{'1','2','3'},{4,5,6},{7,8,9}})
{{'1',4,7},{'2',5,8},{'3',6,9}}
The extra part:
#(x) feval(#(varargin) varargin{3-varargin{1}}(), iscell(x), x, num2cell(x))
is an if statement within an anonymous function that calls num2cell if any sub element is a vector
Say I have a cell array of (n X 1) vectors, A, and a cell array of vectors containing indices into A, called B. I wish to extract a cell array, C, such that C{i} = [A{B{i}}].
In other words, I have a cell array of arrays of indices, and I want to pull out the matrices corresponding to the concatenations of the vectors in A indexed by each of those arrays of indices.
for i = 1:length(B)
%# B{i} is an array of indices, C{i} is a matrix
C{i} = [ A{ B{i} } ];
end
The loop is equivalent to:
C = cellfun(#(x)[A{x}],B,'UniformOutput',false); %# implicit for loop w/ closure
Can I do that using an indexing expression alone? Or at least without the loop?
I think deal() might have to be involved but can't figure it out.
Here are two alternative solutions:
Collect all the indices of B together with the function cell2mat, index the contents of A to make one large matrix, then divide that matrix up using the function mat2cell and the sizes of the index arrays in B:
N = size(A{1}); % Size of an array in A
M = cellfun('prodofsize', B); % Array of sizes of elements in B
C = mat2cell([A{cell2mat(B)}], N, M);
Here's a more compact version of your cellfun-based solution:
C = cellfun(#(x) {[A{x}]}, B);
Ultimately, I would decide what solution to use based on speed and readability, which may actually turn out to be your for-loop-based solution.
Try the following expression:
C = A(cell2mat(B))
You may have a look at Loren's blog post about Cell Arrays and Their Contents