Breaking down a cell - matlab

I have a cell (47,1), where each element is itself a cell (12,1), and each of those 12 cells contains a double (31,1). This means I have 17484 values. How can I extract all those values into one cell (17484,1)?

If I understand your problem correctly, you have a nested array of cells (47 x 1) where each cell is another 12 x 1 cell and each cell is a 31 x 1 array.... that's a pretty awful way to store data... but let's go with the flow.
The command you'd enter in MATLAB is, assuming your matrix is stored in A:
B = reshape(cell2mat(cellfun(#cell2mat, A, 'uni', 0)), 1, []);
Let's break this up step-by-step and explain as we go:
cellfun(#cell2mat, A, 'uni', 0)
cellfun is a function that iterates over all cells in a cell array and applies a function to it. Each cell in A would be a 12 x 1 cell array where each cell is a 31 x 1 matrix. In our case, we use the function cell2mat to take all of these cells that are 31 x 1 matrices and concatenate them into a 31 x 12 matrix. The uni=0 flag means that the output of cellfun is not a uniform numeric matrix. Instead, the output of cellfun will be a 47 cell array where each cell element is a 31 x 12 matrix.
cell2mat(...#1...)
This concatenates all of the 31 x 12 matrices together so that we get a 31 x 564 matrix as the output from step #1 is another cell array.
B = reshape(...#2..., [], 1);
The final step is to take this matrix and reshape the matrix into a single vector of size 17484 x 1. This takes each column of the intermediate matrix in step #2 and places them all into a single vector. B contains this output vector.
If for some reason you want to place each element into an individual cell, you can use the undocumented function sprintfc to take each element in the output B and put them into individual cells:
Bcell = sprintfc('%f', B);

First of all, if you can change the data structure, change it to a 47 by 12 by 31 double. Doing so one of the many advantages is that you probably don't need to do this conversion at all and use linear indices.
%some example data
X=rand(4,5,6)
%3d indexing
X(1,2,3)
%linear indexing
X(3)
%Converting to 1-d:
X=X(:)
If you want to stick with your data structure, you can use X=[X{:}]. Each call of this code merges the two outer levels of your data structure to one cell, thus you have to call it twice.
X=[X{:}]
X=[X{:}]
%There are only very few cases, where numeric data should be stored in a cell. Conciser removing the last line to get a vector.
X=num2cell(X)

Related

Converting 5D cell containing 1x5 double elements into matrix

I have a cell which is of dim x{5,5,5,7,4} and each element it contains is a 1x5 double. I want to convert x from cell to matrix or double. Now when I open x it just says the elements are 1x5 double. How to do this?
If all of your elements are 1x5 double arrays, then you can use cat (combined with {:} indexing) to concatenate all contents along the first dimension
result = cat(1, x{:})
I think this should work with a combination of eval or feval and cell2mat, which gives you a matrix out of a cell.
You can only use cell2mat on the 'second-lowest' level of the cell, so in this solution you would have to iterate through 4 the 5 dimensions of your cell to give every second-lowest-level cell x{k}{l}{m}{n} a name like 'M_int2str(k)_int2str(l)_int2str(m)_int2str(n)' with eval. After that, concatenate the resulting 5*5*5*7 matrices in a way you would like it.
Another - probably easier and faster - possibility would be to create a cell-pyramid with cell2mat. A shorter example:
C={{[1,2,3],[4,5,6]},{[7,8,9],[10,11,12]}};
for k=1:2
M{k}=cell2mat(C{k});
end
N=cell2mat(M)
The result of this is
N =
1 2 3 4 5 6 7 8 9 10 11 12.

Matlab - Two Column Matrices into One Column Matrix with rows elements

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');

using ismember for numeric values

I have a 4554 x 1 vector of type double, called company_info,ind_vec. I also have a another 25 x 1 vector which is of type cell array called groups.industy_labels.
groups.industy_labels contains a list of codes which are numeric.
company_info,ind_vec contains the same numeric codes.
I was planning on doing the below, where I use ismember to return the indices for each numeric code in groups.industy_labels and then do a sum on another vector which is realted to company_info,ind_vec, i.e. another 4554 x 1 vector.
[~, index_sub] = ismember(company_info.ind_vec, groups.industy_labels);
groups.industy_exps(:, 1) = accumarray(index_sub, pwgt , [], #sum, 0);
However Matlab is telling me that ismember only takes cell arrays of string. Is there another way of doing this?
Actually the error message is a bit deceptive as you can use ismember for numeric values:
x=[1 3]
y=[1 2]
ismember(x,y) %This will work
You can also use it for cell arrays, but only for strings:
x=[{'a'},{'c'}]
y=[{'a'},{'b'}]
ismember(x,y) %This will work
x=[{1},{3}]
y=[{1},{2}]
ismember(x,y) %This will fail
So in your case, you would want to use it on 2 numeric vectors, rather than 1 numeric vector and 1 cell array:
x=[1,2] %Numeric vector
y=[{1},{2}] %Cell array
y_numeric = [y{:}] %Made into a numeric vector
ismember(x,y_numeric) %This will work
Note that this assumes that each entry in the cell array only contains a number.

How to compare two cell elements in matlab?

I am using two cells for storing the targeted and the expected value of a neural network process in matlab. I have used two 1*1 cell array for storing the values respectively. And here is my code.
cinfo=cell(1,2)
cinfo(1,1)=iter(1,10)%value is retrieved from a dataset iter
cinfo(1,2)=iter(1,11)
amp1=cinfo(1,1);
amp2=cinfo(1,2);
if amp1 == amp2
message=sprintf('NOT DETECTED BY THE DISEASE');
uiwait(msgbox(message));
But when i run the above code, the get the following error :
??? Undefined function or method 'eq' for input arguments of type 'cell'.
Error in ==> comparison at line 38
if amp1 == amp2
How to solve this problem?
The problem is how you indexed things. A 1x1 cell array does not make a lot of sense, instead get the actual element in the single cell, by indexing with curly brackets:
amp1=cinfo{1,1}; # get the actual element from the cell array, and not just a
amp2=cinfo{1,2}; # 1x1 cell array by indexing with {}
if (amp1 == amp2)
## etc...
However, note that if amp1 and amp2 are not scalars the above will act weird. Instead, do
if (all (amp1 == amp2))
## etc...
Use isequal. That will work even if the cell's contents have different sizes.
Example:
cinfo=cell(1,2);
cinfo(1,1) = {1:10}; %// store vector of 10 numbers in cell 1
cinfo(1,2) = {1:20}; %// store vector of 20 numbers in cell 2
amp1 = cinfo(1,1); %// single cell containing a length-10 numeric vector
amp2 = cinfo(1,2); %// single cell containing a length-20 numeric vector
if isequal(amp1,amp2)
%// ...
In this example, which parallels your code, amp1 and amp2 are cell arrays consisting of a single cell which contains a numeric vector. Another possibility is to directly store each cell's contents into amp1, amp2, and then compare them:
amp1 = cinfo{1,1}; %// length-10 numeric vector
amp2 = cinfo{1,2}; %// length-20 numeric vector
if isequal(amp1,amp2)
%// ...
Note that even in this case, the comparisons amp1==amp1 or all(amp1==amp2) would give an error, because the vectors have different sizes.

gathering specific rows from each submatrices or cell arrays

I hope to gather last lines from each submatrix or cell arrays.
I have 17 x 20 cells in matrix name A.
Each submatrices have different number of lines, but same number of columns (total 7 columns, all)
I tried to generate a file, made up of only last rows of each submatrices. My target file's from will be
M = [column1 column2 column3 column4 column5 column6 column7]
% made up of last rows of each submatrices, unknown number of lines, 7 columns
So I tried
for x_cc = 1:20
for y_cc = 1:17
M = A{x_cc, y_cc}(end,:);
end
end
But it is not working, giving the error Subscript indices must either be real positive integers or logicals.
Should I need to define the size first? What operation should be done? or what commands are useful? I tried cellfun, but not sure how can I use here.
Need any help to solve this situation. Thanks~!
First off, it looks like you switched x_cc and y_cc. Since your matrix is 17 x 20, x_cc is the rows and should go to 17, while y_cc will go to 20.
However, the error you're getting is probably coming from trying to index an empty array (one of those contained in A) using end. An example of this error:
a = [];
a(end)
??? Subscript indices must either be real positive integers or logicals.
If you're curious, a method avoiding for loops would look like:
B = cellfun(#(x) x(end,:), A, 'UniformOutput', 0);
M = cell2mat(B(:));
This grabs the last row from each matrix in A, then stacks them vertically and transforms to an array.