2013-04-01 34 views
2

我试图计算下面的矩阵列明智的差异:从矩阵和位移值MATLAB删除NaN值留下

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有效地做到这一点,而无需使用效率低下的发现()每行查询?

+1

这是不明确的,如果你是“跳跃的NaN”,那么为何仍有NaN的在您的示例输出? –

+0

对不起,我添加了这些NaN以确保矩阵是矩形 - 具有更多数字的行将具有更长的差异。他们可以任意地为零。 – ejang

回答

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); 
+2

我得到了一个'Subscripted assignment dimension mismatch'错误。也许你在for循环中的意思是'1:numNN(r)'? –

+0

@EitanT:确实如此 – Jonas

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(1, N - length(x))中的nan函数调用更改为zeros

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 
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); 
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)