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.
Related
I have a 2 dimensional array L, and I am trying to create a vector of linear indices ind for each row of this array.
L=
1 5 25 4 0 0
2 3 3 45 5 6
45 5 6 0 0 0
I am using lenr to store the number of non zero elements in each row (starting from column 1).
lenr=
4
6
3
Then I have 1x45 array RULES. Indices stored in L refer to elements in RULES. Since I want to vectorize the code, I decided to create linear indices and then run RULES(ind).
This works perfectly:
ind=sub2ind(size(L),1,lenr(1));
while this doesn't work:
ind=sub2ind(size(L),1:3,1:lenr(1:3));
Any ideas?
UPDATE:
This is what I initially tried to vectorize the code, but it did not works and that's why I checked linear indices:
rul=repmat(RULES,3);
result = rul((L(1:J,1:lenr(1:J))));
If I correctly interpret your edit, you want to create a variable result that contains the elements of RULES indicated by the non-zero elements of L. Note that in general, the best way to vectorize sub2ind is to not use sub2ind.
If you want result to be a linear array, you can simply write
%// transpose so that result is ordered by row
L_transposed = L.';
result = RULES(L_transposed(L_transposed>0));
If, instead, you want result to be an array of the same size as L, with all numbers in L replaced by the corresponding element in RULES, it's even simpler:
result = L;
result(result>0) = RULES(result>0);
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)
I have five classes of data stored in a cell,
DataCell =
[74035x14 single] [8063x14 single] [7244x14 single] [6895x14 single] [2510x14 single]
I want to get the prior probabilities of each class,
So want it's pretty simple,
SumData = 74032 + 8063 + 7244 + 6895 + 2510;
prior = [74035 8063 7244 6895 2510] / SumData;
I was wondering if there is a way to avoid loop and get the answer.
Thanks,
Store the counts of the DataCell into an array, then "nomalize" it:
data_counts = cellfun(#(x) size(x,1), DataCell);
prior = data_counts / sum(data_counts(:));
The data_counts(:) is just a funny way of summing all the elements of data_counts, no matter what shape they're in.
To add to CST-Link's answer, cellfun has a special flag where if you specify 'size', you can determine the size of of elements inside each cell in a cell array. You simply specify which dimension you're measuring the size of and it'll return an array of elements that denote the size of each cell in a particular dimension. It will also respect whatever the shape of your cell array was before you call cellfun. For example, if you have a 2 x 2 cell array, after using 'size', it will return a 2 x 2 numeric matrix where each element is the size of the dimension you specified.
Therefore, do this:
data_counts = cellfun('size', DataCell, 1);
prior = data_counts / sum(data_counts(:));
To add to the data_counts(:) statement, this is MATLAB's way of unrolling a matrix. What this will do is that it transforms data_counts into a single vector, where it is composed of columns of A stacked on top of each other. For example, if you had a matrix like so:
A =
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Doing A(:) would give you:
1
5
9
13
2
6
10
14
3
7
11
15
4
8
12
16
However, if A is already a 1D array, then this has no effect at all. The only thing that it will do is that if your array was a row vector, this will transform the array so that it's column vector. If it was already a column vector, then this won't change anything. This is a neat trick to ensure that a 1D array is always a column vector.
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.
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.