Index values from cell by comparing with another cell - matlab

I have 2 cells, B and M. B is nx1 cell and M is a nx2 cell. Some of the values in B are blanks. The rest is the same as M{:,2}. Something like this:
B=
'beta001.img'
'beta002.img'
[]
[]
[]
'beta006.img'
[]
...
And
M=
67 'beta001.img'
89 'beta002.img'
34 'beta003.img'
14 'beta004.img'
15 'beta005.img'
32 'beta006.img'
...
I would like to create a cell C that contains values from the 1st column of M but only if the corresponding values in second column match those in B. Basically, with the example above, C should be:
67
89
32
I can see there are at least two options. The easiest would be doing a horzcat of B and M then get rid of all the rows that contain a blank. I tried:
C=horzcat(B,M);
C=R(~cellfun('isempty',C));
Unfortunately that didn't work. Since I want to learn how to use ismember, the second option is to use that to compare across B and M. Could anyone help me?

Your approach corrected:
This concatenates the matrices. Then extracts the rows, where there aren't any empty entries and then the second column of the result.
C = horzcat(B,M);
C = C(~any(cellfun('isempty',C),2),:);
C = cell2mat(C(:,2));
But you don't need to concatenate the cell-arrays to achieve what you are doing.
Simplified approach:
You can just find the lines where B is not empty, and then take the first column of M of said corresponding lines.
isBnotEmpty = ~cellfun(#isempty, B);
C = cell2mat(M(isBnotEmpty,1));

Related

Use Matlab to find all combinations of multiple string arrays

I have three cell arrays of strings and I want to find all possible combinations of the three. So if I have:
One= Two= Three=
[A B [M N [W X
C D] O P] Y Z]
I want to be able to find all combinations, which would give me something like:
Four=
[AMW AMX AMY AMZ ANW ANX ANY ANZ AOW AOX AOY AOZ APW APX APY APZ
BMW BMX BMY BMZ BNW BNX BNY BNZ BOW BOX BOY BOZ BPW BPX BPY BPZ
etc.
etc.]
Is there a simple way to do this or will I have to somehow change the strings to integer values?
So, you have three cell arrays:
One = {'A' 'B' 'C' 'D'};
Two = {'M' 'N' 'O' 'P'};
Three = {'W' 'X' 'Y' 'Z'};
We can try to work with their indices
a = 1:length(One);
ind = combvec(a,a,a);
ind would be the matrix with all the combinations of three numbers from 1 to 4, e.g. 111 112 113 114 211 212 213 214 etc. According to combinatorics, its dimensions would be 3x64. The indices correspond to the letters in your cell array, i.e. 214 would correspond to 'BMZ' combination.
EDIT, developed an easy way to generate the combinations without combvec with help of #LuisMendo 's answer:
a=1:4;
[A,B,C] = ndgrid(a,a,a);
ind = [A(:),B(:),C(:)]';
Then you create the blank cell array with length equal to 64 - that's how many combinations of three letters you are expected to get. Finally, you start a loop that concatenates the letters according to the combination in ind array:
Four = cell(1,length(ind(1,:)));
for i = 1:length(ind(1,:))
Four(i) = strcat(One(ind(1,i)),Two(ind(2,i)),Three(ind(3,i)));
end
So, you obtain:
Four =
'AMW' 'BMW' 'CMW' 'DMW' 'ANW' ...

Breaking down a cell

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)

Assign values from vector to a specific part of another vector [Matlab]

I am fairly new to matlab. I am sure there is a nice way to do this.
I have the vector h which contains 1257 elements.
And I have the vector t which contains 101 elements.
What I want is to assign the vector t from the 529th to the 630th element from vector h.
I tried this:
h(529:630) = t;
Then I get this message: "In an assignment A(I) = B, the number of elements in B and I must be the same."
If I use a scalar it works. For example:
h(529:630) = 5;
No problem there.
Can someone come up with something clever :)?
Thx
h(529:630) will have 630 - 529 + 1 = 102 elements
>> length(h(529:630))
ans =
102
You must use :
h(530:630) = t ;
Or
h(529:629) = t ;
whatever the case may be.

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.

MATLAB using MAT2CELL

i have the following matrices
letter=[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ...
a b c d e f g h ii jj k l m o p q r s t u v w x y z];
number=[one two three four five six seven eight nine zero];
character =[number letter];
Character becomes a matrix of 42 by 1464, but i would like to break it into cells of 42 by 24 using mat2cell.
How can i please do it, every time i try i get an error????
The example matrices you give don't make much sense given the problem you describe in the text. If you have a matrix of size 42-by-1464, and you want to use MAT2CELL to break it up into a cell array containing elements that are 42-by-24, you can do the following:
mat = repmat('a',42,1464); %# A sample character matrix containing all 'a's
[nRows nCols] = size(mat); %# Get the number of rows and columns in mat
nSubCols = 24; %# The number of desired columns in each submatrix
cellArray = mat2cell(mat,nRows,nSubCols.*ones(1,nCols/nSubCols));
The second input to MAT2CELL defines how the rows will be broken up among cells along the row dimension. In this case, a single value of 42 (i.e. nRows) indicates that the resulting cell array will have one row and the cells will contain matrices with 42 rows.
The third input to MAT2CELL defines how the columns will be broken up among cells along the column dimension. In this case, it is a 61 element (i.e. nCols/nSubCols) row vector whose elements all contain the number 24 (i.e. nSubCols). This indicates that the resulting cell array will have 61 columns and the cells will contain matrices with 24 columns.
The net result is that cellArray ends up being a 1-by-61 cell array where each cell contains a 42-by-24 submatrix of mat.
The above works when nCols is an exact multiple of nSubCols. If it isn't, then you will have to distribute columns to your cells in a heterogeneous manner (i.e. each cell may have a different number of columns in its submatrix). Some ways to deal with such a situation are discussed in this other SO question.