Use Matlab to select specific nonzero values in cell array

3 views (last 30 days)
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
dpb
dpb on 7 Dec 2015
I can't decipher the rule for which elements are in the corresponding output rows...how is it constructed again????
Jana Smith
Jana Smith on 8 Dec 2015
In the output I will have the number beside its corresponding row 1 and column 1 values.

Sign in to comment.

Answers (3)

Guillaume
Guillaume on 8 Dec 2015
Edited: Guillaume on 8 Dec 2015
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.

Walter Roberson
Walter Roberson on 7 Dec 2015
Edited: Walter Roberson on 7 Dec 2015
[r, c, v] = find(One);
Output = [v, One(r,1), One(1,c)]
  1 Comment
Guillaume
Guillaume on 8 Dec 2015
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.


Stephen23
Stephen23 on 9 Dec 2015
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

Find more on Characters and Strings in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!