【问题标题】:How to trim leading and trailing NaN values from n-dimensional array?如何从 n 维数组中修剪前导和尾随 NaN 值?
【发布时间】:2012-08-15 03:36:42
【问题描述】:

这在两个维度上很容易,例如:

>> 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 大得多。

【问题讨论】:

  • 你知道你可以做A = NaN(5,4)吗?在 Matlab 中,NaN 既是双精度指令又是矩阵生成指令

标签: matlab multidimensional-array trim nan


【解决方案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-调用。但我不知道这在多大程度上很重要 - 也许有人可以发表评论......

【讨论】:

  • s 未在您的解决方案中定义。您显然不知道如何估计算法性能。 all 调用可能比isnan 调用花费更少的时间 - 算法复杂度相等,MATLAB 可能实现了位集。
  • 我替你把s改成了size(A)
【解决方案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.

【讨论】:

  • 丑得要命,但是...我认为去这里的唯一方法:)
  • 很抱歉质疑您的解决方案的性能,谢谢您说清楚...所以,我了解到all 速度如此之快,以至于在这里无关紧要...但是我的代码失去了时间在ind2sub 通话中,对吧?
  • 时差其实是相当不重要和做作的。任何数量的因素都会改变它的执行速度,即使对于相同大小的矩阵也是如此。实际上,更快的方法取决于有多少 NaN 值以及 NaN/非 NaN 值在哪里。重要的是两者都具有相同的“算法复杂性”,并且常数大致相同。 IE。它们都花费相似的时间(时间相差不超过 3 倍)
猜你喜欢
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
相关资源
最近更新 更多