matlab - 以快速、矢量化的方式将二进制矩阵转换为最后一个非零索引的矢量

标签 matlab matrix vector vectorization

假设,在 MATLAB 中,我有一个矩阵 A,其元素为 0 或 1。

如何以更快的矢量化方式获取每列最后一个非零元素的索引向量?

我可以

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

并使用I,但是有更快的方法吗? (我假设 cumsum 即使对 0 和 1 求和也会花费一些时间)。

编辑:我想我矢量化的速度甚至超过了我需要的速度 - Mr. Fooz 的循环很棒,但 MATLAB 中的每个循环似乎都花费了 调试时间,即使它很快。

最佳答案

您应该担心的是速度,不一定是全矢量化。最新版本的 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 快得多,但比循环版本慢。

关于matlab - 以快速、矢量化的方式将二进制矩阵转换为最后一个非零索引的矢量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/831721/

相关文章:

matrix - 如何使用 printf 以 Octave 形式打印矩阵值

algorithm - MATLAB 中的 N x N 单位矩阵

c++ - 根据索引移除 vector 元素

excel - 在 Excel 中打印 MATLAB 图窗并调整其大小

matlab - 整数编码

matlab - MATLAB 中的高效 3D 逐元素运算

c++ - 使用复制算法在 C++ 中打印 vector 的格式问题

matlab - 对于 MATLAB 中的大型稀疏矩阵,计算非零条目的各列的累积和?

matlab - 获取综合向量值

c++ - 制作一个抽象类类型的集合,shared_ptr的抽象类 vector