Search elements of matrix in another cell in matlab - arrays

I have a column matrix and a cell array which has two columns.The first column has 1x2 doubles and the second column has 1x1 doubles.
For example
columnMatrix = [1;5];
cellArray = {[1,8],[10];[8,1],[20];[4,6],[80];[3,5],[40];[14,16],[85];[5,10],[36]};
I would like to search each element of columnMatrix in cellArray(:,1) and then return its corresponding value in cellArray(:,2)
For example the output has to be like this
newCell = {[1],[10,20];[5],[40,36]};
I tried using the ismember function in this way
[~,idx] = ismember(cell2mat(cellArray(:,1)),columnMatrix (: , 1));
This returns all the indices which have the searched element but they are in two seperate columns and I can not perform any other logical operation to get the corresponding second column entry.
Is there some way this operation can be achieved? Could some one please help?
Thanks

First of all, convert first column of cellArray to a matrix so it would be easier to search values in. Then iterate over columnMatrix values (e.g. using arrayfun, but you could also use for loop), find rows that match (any across columns) and select corresponding values from the second column of cellArray, converting to numeric array ([cellArray{...,2}]). Finally, append the columnMatrix as the first column of the resulting cell array:
columnMatrix = [1;5]; cellArray = {[1,8],[10];[8,1],[20];[4,6],[80];[3,5],[40];[14,16],[85];[5,10],[36]};
mat = cell2mat(cellArray(:,1));
values = arrayfun(#(x) [cellArray{any(mat==x,2),2}], columnMatrix, 'uni', false);
result = [num2cell(columnMatrix), values];

Related

Targeting specific elements of cell arrays (Matlab)

I currently have a cell array consisting of 7x1 vectors. I need to extract the first element (1,1) of each vector from each cell and store these values in a new array. This is what I currently have:
for j = 1:numel(xvalues)
cellj = xvalues{j};
a = cellj(1:1);
avalues(1:j) = a;
end
However, I am just generating a cell array with the first element of the last cell, repeating.
How can I fix this?
You can also use cellfun to apply a function to each element in a cell array. So to extract the first element of each vector the following should work.
avalues = cellfun(#(x) x(1),xvalues);
Cellfun loops through each element in the cell array and passes it in to the anonymous function via #(x). We then process x by taking the first element x(1).
In cases such as yours, where the cell contents are matrices of the same size, and assuming your inputs are small enough (meaning that neither memory nor runtime are imminent issues) you can convert the cell array into a numeric matrix and select a vector along the relevant dimension:
function out = q48740494
%% Generate some data:
c = squeeze(num2cell(randi(20,7,1,20),[1,2]));
% c = 20×1 cell array of {7x1 double}
%% Convert this into a numeric array and output:
out = cell2mat(c.'); out = out(1,:);
% BONUS: another version of the line above.
% out = subsref(cell2mat(c.'), substruct('()', {1,1:numel(c)}) ) ;

MATLAB indexing all the cells in a cell array of matrices

I have a cell array where each cell contains a matrix (different sizes). I would like, e.g., to take all the second columns of the matrices providing a command like:
aux = cArray{:}(:,2)
The result I'd like to obtain is a cell array where each cell contains the second column of the original matrix, but the command doesn't work (and I can even see why, since the output of cArray{:} is not a matrix ... )
Is there a compact command to get what I want instead of a cycle filling up the cell array ?
The reason why it doesn't work is that indexing a cell array with {:} produces a comma-separated list, which is not indexable anymore. You can view it as the "unwrapped" contents of the cell array separated by commas.
You can achieve what you want with cellfun:
result = cellfun(#(x) x(:,2), cArray, 'uniformoutput', false);
This applies the anonymous function #(x) x(:,2) to each cell's contents, and packs the results in a cell array.

Split matrix into several depending on value in Matlab

I have a cell array that I need to split into several matrices so that I can take the sum of subsets of the data. This is a sample of what I have:
A = {'M00.300', '1644.07';...
'M00.300', '9745.42'; ...
'M00.300', '2232.88'; ...
'M00.600', '13180.82'; ...
'M00.600', '2755.19'; ...
'M00.600', '15800.38'; ...
'M00.900', '18088.11'; ...
'M00.900', '1666.61'};
I want the sum of the second columns for each of 'M00.300', 'M00.600', and 'M00.900'. For example, to correspond to 'M00.300' I would want 1644.07 + 9745.42 + 2232.88.
I don't want to just hard code it because each data set is different, so I need the code to work for different size cell arrays.
I'm not sure of the best way to do this, I was going to begin by looping through A and comparing the strings in the first column and creating matrices within that loop, but that sounded messy and not efficient.
Is there a simpler way to do this?
Classic use of accumarray. You would use the first column as an index and the second column as the values associated with each index. accumarray works where you group values that belong to the same index together and you apply a function to those values. In your case, you'd use the default behaviour and sum things together.
However, you'll need to convert the first column into numeric labels. The third output of unique will help you do this. You'll also need to convert the second column into a numeric array and so str2double is a perfect way to do this.
Without further ado:
[val,~,id] = unique(A(:,1)); %// Get unique values and indices
out = accumarray(id, str2double(A(:,2))); %// Aggregate the groups and sum
format long g; %// For better display of precision
T = table(val, out) %// Display on a nice table
I get this:
>> T = table(val, out)
T =
val out
_________ ________
'M00.300' 13622.37
'M00.600' 31736.39
'M00.900' 19754.72
The above uses the table class that is available from R2013b and onwards. If you don't have this, you can perhaps use a for loop and print out each cell and value separately:
for idx = 1 : numel(out)
fprintf('%s: %f\n', val{idx}, out(idx));
end
We get:
M00.300: 13622.370000
M00.600: 31736.390000
M00.900: 19754.720000

How to remove a row from a matrix inside a cell array

I have a cell array (A) with size of 400 x 1 and each cell of this array includes a matrix with size 9 x 4. As such, it looks like this:
A={[9x4 double];[9x4 double];...;[9x4 double]};
Now, I want to remove the zero rows from these sub matrices and then obtain a new A cell array called A_new where its sub matrices don't have any zero rows like this:
A_new={[5x4 double];[7x4 double];...;[4x4 double]};
By my below code, I can find the index of rows which are not zero but I couldn't create my cell array like I mentioned above. This is my written code and for the bold part, I have a problem and I couldn't solve it.
for i=1:A_Length
[row,col]=find(A{i,1});
out=[row col];
NNZ_row=unique(row);
Length_NNZ= length(NNZ_row);
for j=1:Length_NNZ
**A_NonZero{i,1}= ??????????**
end
end
What I would do is take each cell, then use all on the opposite of the matrix over all of the columns in each row to determine which rows contain all zeroes. Once you do this, use these locations and remove those rows from this matrix and save this to your new matrix.
As such, do this:
A_new = cell(1,numel(A));
for i=1:numel(A)
mat = A{i};
ind = all(~mat, 2);
A_new{i} = mat(~ind,:);
end
The first line of code creates a new cell array that is the same size as A. Next, for each element in A, extract the matrix at each cell location, use all on the opposite of this matrix to find those elements that we need to keep, then save this new matrix into the corresponding location in A_new.
If you want to do this in a single line of code, use cellfun:
A_new = cellfun(#(x) x(~all(~x,2),:), A, 'uni', 0);
The first argument to cellfun is an anonymous function that performs what the for loop was doing. We find those rows that contain all zeroes and use those to remove the rows in each matrix in the cell array. The second argument is the matrix we want to operate on, which is A. The 'uni' and 0 flags are important because the outputs are not single values but matrices, and so the output of this function will be a cell array that is the same size as A where each element is the matrix for those corresponding locations in A with the zero rows removed.
You should use a combination of cellfun and any:
A_new = cellfun(#(x) x(any(x~=0,2),:), A, 'UniformOutput', false);
should do the trick.

Sum along absolute values in an Array in Matlab

My array contains a string in the first row
how can I sum the array from the 2nd row to the Nth/1442th row (as in my example) disregarding the negative signs present in the column?
for example, my code for an array called data2 is:
S = sum(data2(2,15):data2(1442,15));
so sum all of the elements from row 2 to row 1442 in column 15.
This doesn't work but it also does not have anything to deal with the absolute value of whatever row its checking
data is from a .csv:
You should do something like this:
sum(abs(data(2:1442,15)));
The abs function will find the absolute value of each value in the array (i.e. disregard the negative sign). data(2:1442,15) will grab rows 2-1442 of the 15th column, as you wanted.
EDIT: apparently data is a cell array, so you could do the following, I think:
sum(abs([data{2:1442,15}]));
Ok so it looks like you have a constant column so
data2(2,15) = -0.02
and further down
data2(1442,15) = -0.02 %(I would assume)
So when you form:
data2(2,15):data2(1442,15)
this is essential like trying to create an array but of a single value since:
-0.02:-0.02
ans =
-0.0200
which of course gives:
>> sum(-0.02:-0.02)
ans =
-0.0200
What you want should be more like:
sum(data2(2:1442,15))
That way, the index: 2:1442, forms a vector of all the row references for you.
To disregard the negative values:
your answer = sum(abs(data2(2:1442,15)))
EDIT: For a cell array this works:
sum(abs(cell2mat(data2(2:1442,15))))

Resources