我有一系列具有正值然后是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为零。
实现这一目标的最佳方法是什么?感谢。
答案 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)
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