快速提取另一个向量中的索引分组的向量中元素的频率?

Kri*_*673 3 arrays matlab vectorization

假设我有一个矩阵,A其第一列包含一些项ID,第二列包含0或1.

A=[3    1
   1    0
   4    0
   3    0
   1    1
   2    1
   3    1
   4    0
   2    0
   4    1
   3    1
   4    0
   2    1
   1    1
   2    0];
Run Code Online (Sandbox Code Playgroud)

我想找到哪个项目ID拥有最多1的,并从A提取其条目,一个接一个.所以,我做的事情是这样的,我做一个矩阵B提取所有从A 1项,找到最频繁出现项目ID,freq_item{1}B,然后从提取所有条目A该ID的.然后,删除最频繁项目的所有实例,并搜索下一个最常用的项目.如果两个或多个项目具有相同数量的1,选择具有1的的更大的比例:

B = A(A(:,2)==1,:);
for i=1:size(unique(A(:,1)),1)
   freq_item{i} = A(A(:,1)==mode(B(:,1)),:);
   B = B(B(:,1)~=mode(B(:,1)),:);
end
Run Code Online (Sandbox Code Playgroud)

所以,输出是:

freq_item{1,1}=[3     1
                3     0
                3     1
                3     1]

freq_item{1,2}=[1     0           
                1     1
                1     1]

freq_item{1,3}=[2     1
                2     0
                2     1
                2     0]

freq_item{1,4}=[4     0  
                4     0         
                4     1
                4     0]
Run Code Online (Sandbox Code Playgroud)

但是这段代码需要有引入中间矩阵的开销B.是否有代码可以在不需要中间矩阵的情况下完成此任务,B并且至少与上述代码一样快(即,其时间复杂度小于或等于上面编写的代码的时间复杂度)?

the*_*alk 5

只是另一份工作accumarray:

%// prep
subs = A(:,1);
vals = A(:,2);

%// find id with amximum occurences
[~, id] = max( accumarray(subs,vals) )

%// find indices of that id
idx = find(A == id)

%// filter output
out = A(idx,:)
Run Code Online (Sandbox Code Playgroud)

或更短

[~, id] = max( accumarray(A(:,1),A(:,2)) )
out = A(find(A == id),:)
Run Code Online (Sandbox Code Playgroud)

扩大的视野

%// prep
subs = A(:,1);
vals = A(:,2);

%// find id with maximum occurences and mean values
sums = accumarray(subs,vals)
ratios = accumarray(subs,vals,[],@mean)
rows = 1:numel(sums)

%// distributing 
unsorted = accumarray(subs,1:numel(subs),[],@(x) {A(x,:)} )

%// sorting indices
[~,idx] = sortrows([sums(:),ratios(:),rows(:)],[-1 -2 3])
sorted = unsorted(idx)
Run Code Online (Sandbox Code Playgroud)
sorted{1,2} =

     3     0
     3     1
     3     1
     3     1

sorted{2,2} =

     1     0
     1     1
     1     1

sorted{3,2} =

     2     0
     2     0
     2     1
     2     1

sorted{4,2} =

     4     1
     4     0
     4     0
     4     0
Run Code Online (Sandbox Code Playgroud)