在MATLAB中对向量进行有效循环



在Matlab中,我们有这样的场景:

v =[1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 .... N N N N];

其中v中的元素总是按从1到N的递增顺序,我们知道N的值。我们想计算"1"one_answers"2"的个数。。。v.

当然,我们可以使用如下循环:

for i =  1 : N
    % method A
    tic
    ind = find(v == i)
     ---> do sth with ind 
    t1 = toc;
    % method B
    tic
    ind = v(v == i)
     ---> do sth with ind 
    t2 = toc;
    % method C
    tic
    ind = ismember(v , i)
     ---> do sth with ind 
    t3 = toc;

end

这些方法中每种方法所花费的时间大致等于$t1=0.02 sec$、$t2=0.02 sec$和$t3=0.03 sec$。在我的实际工作中,N是巨大的,整个循环需要2-3个小时!

你有什么想法可以增加这个过程的时间吗?任何想法都值得赞赏。

特定情况:排序输入,仅计数

如果你想得到计数,这里可以建议一些方法。

方法#1:

accumarray(v(:),1)

方法#2:

diff([0 find([diff(v) 1])])

方法#3:

histc(v,1:max(v))

对于性能,我会在diff上下注,然后在accumarray上下注,最后在histc上下注。


一般情况:未排序输入,计数&指数

对于输入向量v未排序的一般情况,您可能还需要对应于每组相同数字的索引,这里有一种将索引存储在单元阵列中的方法-

[~,sort_idx] = sort(v);
sorted_v = v(sort_idx);
counts = diff([0 find([diff(sorted_v) 1])])
indices_per_grp = mat2cell(sort_idx,1,counts);

样品运行-

v =
     2     1     3     3     2     4     1     2     1     1     4     3     4   3
counts =
     4     3     4     3
indices_per_grp{1} =
     2     7     9    10
indices_per_grp{2} =
     1     5     8
indices_per_grp{3} =
     3     4    12    14
indices_per_grp{4} =
     6    11    13

我偏爱这里的bsxfun

counts = sum(bsxfun(@eq,v(:),1:max(v)));

由于它们是经过排序的,您可以提高效率!

怎么样

lastfound = 1;
for i =  1 : N
   % find first location after current pos, where value is i
   indStart = find(v(lastfound:end) == i, 1)
   % find first location, after this, where value is not i
   indEnd   = find(v(indStart:end) ~= i, 1)
   % now you have the range indStart:indEnd-1
   ...
   lastfound = indEnd; % start next one after the end of the current value
 end

即仅从最后找到的项目向前搜索。

我相信find(..., 1)只找到了第一个项目。

最新更新