Remove NaNs in matrices within cell array

15 ビュー (過去 30 日間)
Hannu K
Hannu K 2013 年 11 月 7 日
編集済み: Andrei Bobrov 2013 年 11 月 7 日
I have a matrix that has some data in its columns like this:
A = [1 NaN NaN 1 1; NaN NaN NaN 1 NaN; 1 1 NaN 1 NaN]
I want to extract the non NaN elements so that they are returned in a cell array where a cell holds the non NaN elements of the columns like this:
C = {[1;1],[1],[],[1;1;1],[1]}
This far I have tried to use the cellfun:
C = num2cell(A,1);
C(cellfun(@isnan,C, 'UniformOutput', false)) = [];
But i receive an error: Function 'subsindex' is not defined for values of class 'cell'.
I Managed to use for loop:
C = num2cell(A,1);
for i = 1:length(ct)
inds = isnan(ct{i});
ct{i}(inds) = [];
end
This does the trick, but I'm worried about the performance as A can be huge in my actual code.
Any help is more than welcome!
Edit: typo

採用された回答

Andrei Bobrov
Andrei Bobrov 2013 年 11 月 7 日
編集済み: Andrei Bobrov 2013 年 11 月 7 日
out = cellfun(@(x)x(~isnan(x)),num2cell(A,1),'un',0);
with for-end loop
n = size(A,2);
out = cell(n,1);
for jj = 1:n
out{jj} = A(~isnan(A(:,jj)),jj);
end
with accumarray
s = size(A);
ii = ones(s(1),1)*(1:s(2));
out = accumarray(ii(:),A(:),[],@(x){x(~isnan(x))});
  1 件のコメント
Hannu K
Hannu K 2013 年 11 月 7 日
Thank you! As it turns out, the for-loop approach is quicker.

サインインしてコメントする。

その他の回答 (6 件)

Matt J
Matt J 2013 年 11 月 7 日
編集済み: Matt J 2013 年 11 月 7 日
This does the trick, but I'm worried about the performance as A can be huge in my actual code.
Cellfun is usually less efficient than a for-loop. It basically runs a for-loop internally, but in a slightly less efficient way than a direct for-loop.
Also, even though A is huge, length(ct) will not be, correct? If length(ct) is really huge, that's a bigger problem than the question of whether to use cellfun or for-loops. It means you'll have lots of data scattered discontiguously in RAM and access to the cell contents will be very slow.
  1 件のコメント
Hannu K
Hannu K 2013 年 11 月 7 日
Thank you for the insight. I always thought that cellfun does some magic that outperforms the for loop.

サインインしてコメントする。


Matt J
Matt J 2013 年 11 月 7 日
If all elements of A are either NaN or non-zero, then it would be better to convert to a sparse matrix, rather than use cell arrays
[i,j,s]=find(~isnan(A));
[m,n]=size(A);
A=sparse(i,j,s,m,n);

Matt J
Matt J 2013 年 11 月 7 日
Yet another alternative,
map=~isnan(A);
[i,j]=find(map);
k=histc(j,1:size(A,2));
C=mat2cell(A(map),k,1).';

Azzi Abdelmalek
Azzi Abdelmalek 2013 年 11 月 7 日
out1=arrayfun(@(x) A(~isnan(A(:,x)),x),1:size(A,2),'un',0)

David Sanchez
David Sanchez 2013 年 11 月 7 日
for single line solution, A. Abdelmalek's is the solution. You can perform the same by using the following:
A = [3 NaN NaN 2 4; NaN NaN NaN 5 NaN; 6 7 NaN 8 NaN];
[rows cols] = size(A); % number of rows and columns in your matrix
D = mat2cell(A,rows,ones(1,cols)); % cell to hold your data
for k=1:numel(D)
C = ~isnan(D{k});
D{k}(C==0) = [];
end
It works with values different to 1 and the code is quite readable.

Bob Freeman
Bob Freeman 2013 年 11 月 7 日
do find(NaN == 0)

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by