i have matrix C01 <0>, matrix C02 <50x1800 double>, matrix C3 <50x34 double> and i need to transform it to one thing C(i), for using expression like this C(1) = C01, C(2) = C02.
You need to use cell array and refer individual elements as C{1} = C01, C{2} = C02, etc.
You can also create the cell array as C = {C01, C02, C03};
Notice that you still can use C(1) syntax for cell array, but this statement will return not the original numeric matrix, but the matrix encapsulated into a cell array with one element.
Related
I have a matrix, say
A= zeros(5,5,5,5);
and assigned a decimal value for each cell
Now I want to add a character 'x' for every cell
How should I do it?
I have tried to convert A to cell matrix using num2cell
but when I add the 'x' to it, I got the out of range warning and my value disappeared, leaving a single 'x' in every cell
A=zeros(5,5,5,5)
%some calculation for some decimal value
for %something
assign value to every cell
end
A=num2cell(A)
A=concat(A,'x')
If you want to transform 3 to 3x, you cannot store it in a number format any longer, but you have to transform it to string. However, once it is a string, it's very easy to add a letter:
A = zeros(5,5,5,5);
%// fill A with numbers
%// convert to cell
C = num2cell(A);
%// transform all numbers in C to strings using num2str
%// and add the letter 'x' by catenation
%// cellfun applies the function to each element of the cell array
C = cellfun(#(x)[num2str(x),'x'], C, 'UniformOutput', false);
Note that as #Daniel correctly states, you can skip a step in the process and run arrayfun(#(x)[num2str(x),'x'], A, 'UniformOutput', false); on the numeric array directly - the 'UniformOutput',false statement means that arrayfun will return the results in a cell array.
similarly:
B = cell(5,5,5,5);
D = cellfun(#(c) [c '0'],B,'UniformOutput',0);
E = cellfun(#(c) [c 'x'],D,'UniformOutput',0);
I have a 1-by-4 cell array, D. Each of the cell elements contains 2-by-2 double matrices. I want to do random permutation over each matrix independently which in result I will have the same size cell array as D but its matrices' elements will be permuted and then the inverse in order to obtain the original D again.
for a single matrix case I have the code and it works well as follows:
A=rand(3,3)
p=randperm(numel(A));
A(:)=A(p)
[p1,ind]=sort(p);
A(:)=A(ind)
but it doesn't work for a cell array.
The simplest solution for you is to use a loop:
nd = numel(D);
D_permuted{1,nd} = [];
D_ind{1,nd} = [];
for d = 1:nd)
A=D{d};
p=randperm(numel(A));
A(:)=A(p)
[~,ind]=sort(p);
D_permuted{d} = A;
D_ind{d} = ind;
end
Assuming your D matrix is just a list of identically sized (e.g. 2-by-2) matrices, then you could avoid the loop by using a 3D double matrix instead of the cell-array.
For example if you hade a D like this:
n = 5;
D = repmat([1,3;2,4],1,1,n)*10 %// Example data
Then you can do the permutation like this
m = 2*2; %// Here m is the product of the dimensions of each matrix you want to shuffle
[~,I] = sort(rand(m,n)); %// This is just a trick to get the equivalent of a vectorized form of randperm as unfortunately randperm only accepts scalars
idx = reshape(I,2,2,n);
D_shuffled = D(idx);
I have two column matrices:
size(X) = 50 x 1
size(Y) = 50 x 1
which I got from ind2sub
I want to create a structure str such that
str(i).XYZ returns [X(i), Y(i)] for i in [1,50]
I am trying to use
str = struct('XYZ', num2cell([X,Y]));
However, I believe for this to work properly, I need to modify [X,Y] to a matrix of row vectors, each row vector being [X(i), Y(i)]. Not sure if there is a better approach
You are basically on the right way, but num2cell([X,Y]) creates a 2x50 cell, which results in a 2x50 struct. You want to split your input matrix [X,Y] only among the second dimensions so each cell is a 2x1, use num2cell([X,Y],2)
str = struct('XYZ', num2cell([X,Y],2));
Concatenate the two vectors, convert from matrix to cell, and then from cell to struct array:
str = cell2struct(mat2cell([X Y], ones(1,size(X,1)), size(X,2)+size(Y,2) ).', 'XYZ');
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