Use Matlab to select specific nonzero values in cell array

I have a cell array (where the letters are strings and numbers are integers) like so:
One=
[0 A B C
A 0 5 6
B 1 0 2
C 3 4 0]
And I would like to find everywhere the value does not equal 0... And then take that value and the corresponding values in the leftmost column and topmost row and place them in a new array. So I would get something like this:
Output=
[5 A B
6 A C
1 B A
2 B C
3 C A
4 C B]
Are there any simple ways to accomplish this?

4 Comments

If you see this document which is find , you will probably find the answer.
I was actually just trying to incorporate 'find'. I'm still rather new to Matlab so it's been a lot of trial and error.
I can't decipher the rule for which elements are in the corresponding output rows...how is it constructed again????
In the output I will have the number beside its corresponding row 1 and column 1 values.

Sign in to comment.

Answers (3)

First, please use valid matlab syntax for your examples. In particular don't use matrix syntax [] when you have cell arrays that use {} to enclose the elements.
If you can't be bothered to write a valid example, why should we bother answering? A proper example would also remove any ambiguity about what type of data we're working with
One = {0 'AA' 'BB' 'CC'
'AA' 0 5 6
'BB' 1 0 2
'CC' 3 4 0}
%a cell array with numbers and strings. I assume the strings are more than one character
Because you're dealing with cell arrays, it makes everything more complicating. Most functions, such as find don't work with cell arrays. You have to loop over the individual elements, which you can do with cellfun.
First thing is to find the numbers in your cell array and identify which ones are non-zero:
nonzeronumbers = cellfun(@(c) isnumeric(c) && c, One) %Use the shortcircuit properties of && so that c is only evaluated when numeric
The two output form or find will then return the rows and columns of the non-zero numbers:
[row, col] = find(nonzeronumbers)
The final output is generated with:
Output = [One(sub2ind(size(One), row, col)), One(row, 1), One(1, col)']
Note that the order is by column instead of row since that's how matlab work. If you really want in row order, you'll have to do some transposing before find and in the output.
[r, c, v] = find(One);
Output = [v, One(r,1), One(1,c)]

1 Comment

This of course won't work if One is indeed a cell array as said in the first sentence but not shown in the example.

Sign in to comment.

Try this:
X = {0,'A','B','C';
'A',0, 5, 6;
'B',1, 0, 2;
'C',3, 4, 0};
%
Y = X(2:end,2:end)';
M = cell2mat(Y);
[C,R] = find(M);
Z(3,:) = X(1,1+C);
Z(2,:) = X(1+R,1);
Z(1,:) = Y(M>0)
But perhaps the cell array is not the optimal data storage for this data: it seems that you are trying to replicate the functionality of a table using a cell array, complete with row and column names. I would suggest that keeping the data and the row/column names separate would be a much better data storage idea, as this would mean accessing them would be simpler. Also in your case the data could be stored as a simple numeric array, which makes many many calculations much easier. It would look something like this:
row_names = {'A','B','C'};
col_names = {'A','B','C'};
data_mat = [0,5,6;1,0,2;3,4,0];
and the rest is essentially the same as above, plus a num2cell or the like.

Categories

Products

Asked:

on 7 Dec 2015

Answered:

on 9 Dec 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!