假设,在MATLAB,我有一个矩阵,一个,其元素都是0或1。

我怎么得到的矢量指数的最后一个非零件的每个列在一个速度更快,矢量的方式?

我可以做的

[B, I] = max(cumsum(A));

和使用 I, 但是有一个更快速方式?(我假设cumsum会花费一点时间甚至素明0和1)。

编辑: 我想我矢量的甚至比我更需要的快先生Fooz'循环是巨大的,但每个环MATLAB中似乎成本 很多在调试的时间,即使它是快。

有帮助吗?

解决方案

如由 先生Fooz, 为循环,可以很快与较新版本的MATLAB。但是,如果你真的想要有紧凑的矢量的代码,我建议试图:

[B,I] = max(flipud(A));
I = size(A,1)-I+1;

这是速度比你的CUMSUM基于答案,但仍然不是很快,先生Fooz的循环的选择。

另外两个要考虑的事项:

  • 什么样的结果,你想要得到的列有没有人在这吗?与上述的选择我给了你,我相信你会得到一个指数 大小(1) (即行数 一个)在这样的情况。为你的选项,我相信,你将获得1在这样的情况,而嵌套循环的选择从先生Fooz会给你一个0.

  • 相对速度的这些不同的选项很可能会根据不同大小的 一个 并非零你指望它有。

其他提示

快速是你应该担心的,不一定是完全矢量化。 Matlab的最新版本对于有效处理循环非常聪明。如果有一种紧凑的矢量化表达方式,它通常会更快,但循环不应该(总是)像以前那样担心。

clc

A = rand(5000)>0.5;
A(1,find(sum(A,1)==0)) = 1; % make sure there is at least one match

% Slow because it is doing too much work
tic;[B,I1]=max(cumsum(A));toc

% Fast because FIND is fast and it runs the inner loop
tic;
I3=zeros(1,5000);
for i=1:5000
  I3(i) = find(A(:,i),1,'last');
end
toc;
assert(all(I1==I3));

% Even faster because the JIT in Matlab is smart enough now
tic;
I2=zeros(1,5000);
for i=1:5000
  I2(i) = 0;
  for j=5000:-1:1
    if A(j,i)
      I2(i) = j;
      break;
    end
  end
end
toc;
assert(all(I1==I2));

在R2008a,Windows,x64上,cumsum版本需要0.9秒。循环和查找版本需要0.02秒。双循环版仅需0.001秒。

编辑:哪一个最快取决于实际数据。当你将0.5改为0.999时,双循环需要0.05秒(因为它需要更长的时间才能达到平均值)。 cumsum和loop& find实现具有更加一致的速度。

编辑2: gnovice的flipud解决方案很聪明。不幸的是,在我的测试机器上需要0.1秒,所以它比cumsum快得多,但比循环版本慢。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top