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

use*_*235 1 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
Run Code Online (Sandbox Code Playgroud)

如果是这个矩阵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
Run Code Online (Sandbox Code Playgroud)

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

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

Div*_*kar 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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

方法#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
Run Code Online (Sandbox Code Playgroud)


Joa*_*son 5

Divakar的解决方案运行良好,但作为替代解决方案,您可以使用两个嵌套cumsum来获取每行第一个NaN的掩码,并使用它将这些值重置为0;

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
Run Code Online (Sandbox Code Playgroud)