我有4x2矩阵A:
A = [2 NaN 5 8; 14 NaN 23 NaN]';
我想用A中每列中的相关索引替换非NaN值。输出如下所示:
out = [1 NaN 3 4; 1 NaN 3 NaN]';
我知道如何手动为每列操作,但我想要一个自动解决方案,因为我有更大的矩阵可以处理。任何人有任何想法?
答案 0 :(得分:11)
out = bsxfun(@times, A-A+1, (1:size(A,1)).');
工作原理:
A-A+1
将A
中的实际数字替换为1
,并将NaN
保留为NaN
(1:size(A,1)).'
是行索引的列向量bsxfun(@times, ...)
将上述两种方法与单例扩展相乘。正如@thewaywewalk所指出的那样,在Matlab R2016之后bsxfun(@times...)
可以被.*
取代,因为默认情况下启用了单例扩展:
out = (A-A+1) .* (1:size(A,1)).';
@Dev-Il建议的替代方案是
out = bsxfun(@plus, A*0, (1:size(A,1)).');
这是有效的,因为乘以0
会将实际数字替换为0
,并按原样保留NaN
。
答案 1 :(得分:8)
mask = find(~isnan(A));
[rows,~] = ind2sub(size(A),mask)
A(mask) = rows;
请注意,ind2sub
的第二个输出需要(~
忽略)以及[rows,~]
,以表示您想要输出2D矩阵。
A =
1 1
NaN NaN
3 3
4 NaN
A.' =
1 NaN 3 4
1 NaN 3 NaN
另外请注意两个不同的转置操作符'
和.'
。
[n,m] = size(A);
B = ndgrid(1:n,1:m);
B(isnan(A)) = NaN;
或甚至(Luis Mendo的一点灵感)
[n,m] = size(A);
B = A-A + ndgrid(1:n,1:m)
或一行
B = A-A + ndgrid(1:size(A,1),1:size(A,2))
答案 2 :(得分:6)
A = [ 2 NaN 5 8;
14 NaN 23 NaN];
out=repmat([1:size(A,2)],size(A,1),1); % out contains indexes of all the values
out(isnan(A))= NaN % Replacing the indexes where NaN exists with NaN
<强>输出:强>
1 NaN 3 4
1 NaN 3 NaN
如果需要,您可以进行转置。
答案 3 :(得分:2)
由于以下几个原因,我正在添加另一个答案:
kron
* ahem * )很有趣。A*0
与A-A
相同。
A = [2 NaN 5 8; 14 NaN 23 NaN].';
out = A*0 + kron((1:size(A,1)).', ones(1,size(A,2)))
out =
1 1
NaN NaN
3 3
4 NaN