将非NaN值替换为矩阵内的行索引

时间:2016-10-03 11:51:40

标签: matlab matrix

我有4x2矩阵A:

A = [2 NaN 5 8; 14 NaN 23 NaN]';

我想用A中每列中的相关索引替换非NaN值。输出如下所示:

out = [1 NaN 3 4; 1 NaN 3 NaN]'; 

我知道如何手动为每列操作,但我想要一个自动解决方案,因为我有更大的矩阵可以处理。任何人有任何想法?

4 个答案:

答案 0 :(得分:11)

out = bsxfun(@times, A-A+1, (1:size(A,1)).');

工作原理:

  • A-A+1A中的实际数字替换为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)

ind2sub应用于使用isnan创建的模板。

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)

可以使用repmatisnan完成此操作,如下所示:

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)

由于以下几个原因,我正在添加另一个答案:

  1. 因为矫枉过正( * ahem * kron * ahem * )很有趣。
  2. 要证明A*0A-A相同。
  3. 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