MATLAB从矩阵中移除NaN值并向左移动值

时间:2013-04-01 23:45:31

标签: matlab

我正在尝试计算以下矩阵中的列式差异:

A = 
     0       NaN       NaN    0.3750       NaN
     NaN    0.1250    0.2500  0.3750       NaN

我想获得:

0.3750 NaN    NaN
0.1250 0.1250 0.1250

我基本上采用了列式差异,跳过NaN值并将值移到左侧。

一维案例是:

A = [0 NaN 0.250 0.375 NaN 0.625];
NaN_diff(A) = [0.250 0.125 0.250];

在MATLAB中有效地执行此操作而不使用每行低效的find()查询?

5 个答案:

答案 0 :(得分:4)

这是一个矢量化大部分操作的解决方案:

notNan = ~isnan(A);
numNN  = sum(notNan,2);

shifted = NaN(size(A));

for r = 1:size(A,1)
   myRow = A(r,:);
   shifted(r,1:numNN(r)) = myRow(notNan(r,:));
end

nanDiff = diff(shifted,1,2);

答案 1 :(得分:2)

这是另一种矢量化解决方案:

%// Convert to cell array without NaNs
[rows, cols] = size(A);
C = cellfun(@(x)x(~isnan(x)), mat2cell(A, ones(1, rows), cols), 'Uniform', 0);

%// Compute diff for each row and pad
N = max(sum(~isnan(A), 2));
C = cellfun(@(x)[diff(x) nan(1, N - length(x))], C, 'Uniform', 0);

%// Convert back to a matrix
nandiff = vertcat(C{:});

如果您想使用零而不是NaN值填充结果矩阵,请将nan中的nan(1, N - length(x))函数调用更改为zeros

答案 2 :(得分:0)

这是一种替代方法,它需要您遍历每一行,但仍然应该具有不错的性能并且对我来说非常直观。

B = NaN(size(A,1),size(A,2)-1)

for i = 1:size(A,1)
   idx = ~isnan(A(:,i))
   B(i,1:sum(idx)) = diff(A(i,idx))
end

答案 3 :(得分:0)

我知道这是一个相当古老的问题,但对于像我这样偶然发现这个页面的人来说,这是一个更简单(imho)的解决方案:

A = [0 NaN 0.250 0.375 NaN 0.625];
A(isnan(A))=[]; % identify index of NaN values and remove them from the array
B = diff(A); 

答案 4 :(得分:0)

这是另一个不使用循环的简单解决方案[但假设所有值都按升序排列]:

A=[0       NaN       NaN    0.3750       NaN;NaN    0.1250    0.2500  0.3750       NaN]
A(isnan(A(:,1)))=0;
B=sort(A,2);
C=diff(B,1,2)