MATLAB - 如何用零替换每列中的第一个NaN?

时间:2014-09-14 05:06:30

标签: matlab loops matrix nan

我有一系列具有正值然后是NaN的列,例如:

12    16    10
11    13    9
8     10    7 
7     6     5
4     1     4
2     NaN   2
NaN   NaN   1
NaN   NaN   NaN

如果此矩阵为A,则可以使用以下内容找到每列中第一个NaN的(行)位置:sum(~isnan(A))

我现在想用零替换每个位置的NaN,例如:

12    16    10
11    13    9
8     10    7 
7     6     5
4     1     4
2     0     2
0     NaN   1
NaN   NaN   0

到目前为止,我尝试使用逻辑,索引和循环方法的组合失败了,创建了一个新的矩阵,其中所有NaN都为零,每个找到的行中的所有值都为零,或者仅在第一列或最后一列中的NaN为零。

实现这一目标的最佳方法是什么?感谢。

3 个答案:

答案 0 :(得分:5)

方法#1

[m,n] = size(A) %// get size of input data
[v,ind] = max(isnan(A))  %// positions of first nans in each column
ind2 = bsxfun(@plus,ind,[0:n-1]*m)  %// linear indices of those positions
A(ind2(v))=0 %// set values of all those positions to zero

代码在示例输入上运行(稍微不同于有问题的示例) -

A (Input) =
    12    16    10
    11    13     9
     8    10     7
     7     6     5
     4     1     4
     2   NaN     2
     4   NaN     1
     1   NaN   NaN


A (Output) =
    12    16    10
    11    13     9
     8    10     7
     7     6     5
     4     1     4
     2     0     2
     4   NaN     1
     1   NaN     0

方法#2

如果您想使用sum(~isnan(A)代码,这可能会形成另一种方法,但请注意,这假设一旦NaN元素开始出现在列中,就没有数值,因此#1是更安全的。这是方法#2的代码 -

[m,n] = size(A); %// get size of input data
ind = sum(~isnan(A))+1; %// positions of first nans in each column
v = ind<=m; %// position of valid ind values
ind2 = bsxfun(@plus,ind,[0:n-1]*m);  %// linear indices of those positions
A(ind2(v))=0 %// set values of all those positions to zero

答案 1 :(得分:5)

Divakar的解决方案运行良好,但作为替代解决方案,您可以使用两个嵌套cumsum来获取每行第一个NaN的掩码,并使用它将这些值重置为0; < / p>
A =    
    12    16    10
    11    13     9
     8    10     7
     7     6     5
     4     1     4
     2   NaN     2
   NaN     7     1
   NaN   NaN   NaN

>>> A(cumsum(cumsum(isnan(A))) == 1) = 0

A =

    12    16    10
    11    13     9
     8    10     7
     7     6     5
     4     1     4
     2     0     2
     0     7     1
   NaN   NaN     0

答案 2 :(得分:2)

基于accumarray的方法:

[ii jj] = find(isnan(A)); %// rows and columns of NaNs
ind = accumarray(jj,ii, [], @min); %// minimum row for each column with NaNs
ind = ind(ind~=0); %// a 0 indicates no NaNs in that column, so it should be removed
A(size(A,1)*(unique(jj)-1)+ind) = 0; %// set those entries to 0 using linear indexing

例如,

A = [ 12    16    10
      11    13     9
       8    10     7
       7     6     5
       4     1     4
       2   NaN     2
       4   NaN   NaN
       1     5   NaN ]

转化为

A = 
    12    16    10
    11    13     9
     8    10     7
     7     6     5
     4     1     4
     2     0     2
     4   NaN     0
     1     5   NaN