在MATLAB中有效地循环向量

YAS*_*YAS 2 matlab vector vectorization

在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];
Run Code Online (Sandbox Code Playgroud)

其中v中的元素总是以1到N的递增顺序,我们知道N的值.我们想要计算'1''2'...的数量.

我们肯定可以使用如下循环:

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
Run Code Online (Sandbox Code Playgroud)

这些方法的时间大致等于$ t1 = 0.02秒$,$ t2 = 0.02秒$和$ t3 = 0.03秒$.在我的实际工作中,N很大,整个循环需要2-3个小时!

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

Div*_*kar 6

具体情况:排序输入,仅计数

如果您想获得计数,可以在这里建议几种方法.

方法#1:

accumarray(v(:),1)
Run Code Online (Sandbox Code Playgroud)

方法#2:

diff([0 find([diff(v) 1])])
Run Code Online (Sandbox Code Playgroud)

方法#3:

histc(v,1:max(v))
Run Code Online (Sandbox Code Playgroud)

为了表现,我打赌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);
Run Code Online (Sandbox Code Playgroud)

样品运行 -

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
Run Code Online (Sandbox Code Playgroud)

  • @TroyHaskin我们与Ray在比较`accumarray`和`histc`时做了一些基准测试.`accumarray`基本上疯了.`diff`我知道它非常有效,特别是对于巨大的数组. (2认同)