2

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

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() 查询?

4

5 回答 5

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);
于 2013-04-01T23:56:33.283 回答
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.

于 2013-04-02T00:46:23.803 回答
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
于 2013-05-22T16:04:52.280 回答
0

我知道这是一个相当古老的问题,但是对于像我这样偶然进入此页面的人来说,这里有一个更简单(恕我直言)的问题解决方案:

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); 
于 2014-04-09T09:31:59.533 回答
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)
于 2015-09-01T16:34:03.730 回答