找到向量b的唯一索引的最快方法,其中数组A(i,j)== b

时间:2018-05-31 16:41:28

标签: matlab performance find

我有两个大数组Ab

A:10.000 ++行,4列,不是唯一的整数
b:具有500.000 ++元素的向量,唯一整数

由于b值的唯一性,我需要找到b的唯一索引,其中A(i,j) == b

我开始的是

[rows,columns] = size(A);
B = zeros(rows,columns);
for i = 1 : rows
    for j = 1 : columns
        B(i,j) = find(A(i,j)==b,1);
    end
end

这需要大约 5.5秒来计算,这是很长的方式,因为Ab可能会显着更大......这就是我试图加速通过使用逻辑索引和减少for循环来增加代码

[rows,columns] = size(A);
B = zeros(rows,columns);
for idx = 1 : numel(b)
    B(A==b(idx)) = idx;
end

可悲的是,这需要更长时间: 21秒

我甚至尝试使用bsxfun

for i = 1 : columns
   [I,J] = find(bsxfun(@eq,A(:,i),b))
    ... stitch B together ...
end

但是使用更大的阵列时,最大阵列大小会很快超过(102,9GB ......)。

你能帮我找到更快的解决方案吗?提前谢谢!

编辑:我延长了find(A(i,j)==b ,1 ),这使得算法加速了2倍!谢谢,但整体还是太慢了......;)

2 个答案:

答案 0 :(得分:4)

函数ismember是正确的工具:

[~,B] = ismember(A,b);

测试代码:

function so
  A = rand(1000,4);
  b = unique([A(:);rand(2000,1)]);

  B1 = op1(A,b);
  B2 = op2(A,b);
  isequal(B1,B2)

  tic;op1(A,b);op1(A,b);op1(A,b);op1(A,b);toc
  tic;op2(A,b);op2(A,b);op2(A,b);op2(A,b);toc
end

function B = op1(A,b)
  B = zeros(size(A));
  for i = 1:numel(A)
    B(i) = find(A(i)==b,1);
  end
end

function B = op2(A,b)
  [~,B] = ismember(A,b);
end

我在Octave上运行了这个,它的循环速度不如MATLAB。它也没有timeit函数,因此使用tic / toc的时间很糟糕(抱歉)。在Octave中,op2op1快100多倍。时序在MATLAB中会有所不同,但ismember应该仍然是最快的选择。 (注意我也用单个循环替换了你的双循环,这是相同但更简单,可能更快。)

如果您想在b中重复进行搜索,首先要对b进行排序,并实施自己的二分查找。这将避免ismember所做的检查和排序。请参阅this other question

答案 1 :(得分:2)

假设你有正整数,你可以使用数组索引:

mm = max(max(A(:)),max(b(:)));
idxs = sparse(b,1,1:numel(b),mm,1);
result = full(idxs(A));

如果值的范围很小,您可以使用密集矩阵而不是稀疏矩阵:

mm = max(max(A(:)),max(b(:)));
idx = zeros(mm,1);
idx(b)=1:numel(b);
result = idx(A);