如何从n维数组中修剪前导和尾随NaN值?

时间:2012-08-19 13:44:22

标签: matlab multidimensional-array trim nan

这在两个方面很容易,例如:

>> A = NaN(5,4)
>> A(2:4,2:3) = [1 2; 3 4; 5 6]
>> A(2,2) = NaN                
>> A(4,3) = NaN 

A =

   NaN   NaN   NaN   NaN
   NaN   NaN     2   NaN
   NaN     3     4   NaN
   NaN     5   NaN   NaN
   NaN   NaN   NaN   NaN

>> A(~all(isnan(A),2),~all(isnan(A),1))

ans =

   NaN     2
     3     4
     5   NaN

请注意,保留不是所有NaN的行和列中的NaN值。

如何将其扩展为多个维度?例如,如果A有三个维度:

>> A = NaN(5,4,3)           
>> A(2:4,2:3,2) = [1 2; 3 4; 5 6]
>> A(2,2,2) = NaN                
>> A(4,3,2) = NaN                

A(:,:,1) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

A(:,:,2) =

   NaN   NaN   NaN   NaN
   NaN   NaN     2   NaN
   NaN     3     4   NaN
   NaN     5   NaN   NaN
   NaN   NaN   NaN   NaN


A(:,:,3) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

我如何获得

ans =

   NaN     2
     3     4
     5   NaN

我想在四维中做到这一点,并且在这里使用比示例矩阵A大得多的矩阵。

2 个答案:

答案 0 :(得分:1)

我根据OP发布的输入A解决问题:

>> [i,j,k] = ind2sub(size(A),find(~isnan(A)));
>> l = min([i j k]);
>> u = max([i j k]);
>> B=A(l(1):u(1),l(2):u(2),l(3):u(3))
B =
   NaN     2
     3     4
     5   NaN
>> size(B)
ans =
     3     2

既然你说你想在更大的矩阵上做这个,我不确定@ ronalchn的解决方案的性能 - 这就是所有的all - 调用。但我不知道重要的是什么 - 也许有人可以评论......

答案 1 :(得分:0)

试试这个:

2维

A(~all(isnan(A),2),~all(isnan(A),1))

3维

A(~all(all(isnan(A),2),3),...
  ~all(all(isnan(A),1),3),...
  ~all(all(isnan(A),1),2))

4维

A(~all(all(all(isnan(A),2),3),4),...
  ~all(all(all(isnan(A),1),3),4),...
  ~all(all(all(isnan(A),1),2),4),...
  ~all(all(all(isnan(A),1),2),3))

基本上,规则适用于N维:

  • 在所有N维​​上你做了isnan()的事情。

  • 然后使用all()函数将其包装N-1次,

  • 并且第i个维度的每个all()函数的第二个参数应该是任何顺序的数字1到N,但不包括i。


由于Theodros Zelleke希望看到哪种方法更快(说他认为他的方法如此之快的好方法),这是一个基准。矩阵A定义为:

A = NaN*ones(100,400,3,3);
A(2:4,2:3,2,2) = [1 2; 3 4; 5 6];
A(2,2,2,2) = NaN;A(4,3,2,2) = NaN;
A(5:80,4:200,2,2)=ones(76,197);

他的测试定义为:

tic;
for i=1:100
[i,j,k,z] = ind2sub(size(A),find(~isnan(A)));
l = min([i j k z]);
u = max([i j k z]);
B=A(l(1):u(1),l(2):u(2),l(3):u(3),l(4):u(4));
end
toc

结果:

Elapsed time is 0.533932 seconds.
Elapsed time is 0.519216 seconds.
Elapsed time is 0.575037 seconds.
Elapsed time is 0.525000 seconds.

我的测试定义为:

tic;
for i=1:100
isnanA=isnan(A);
ai34=all(all(isnanA,3),4);
ai12=all(all(isnanA,1),2);
B=A(~all(ai34,2),~all(ai34,1),~all(ai12,4),~all(ai12,3));
end
toc

结果:

Elapsed time is 0.224869 seconds.
Elapsed time is 0.225132 seconds.
Elapsed time is 0.246762 seconds.
Elapsed time is 0.236989 seconds.