将大向量中的每个元素分配给重复次数的有效方法

Efficient way to assign each element in a large vector to the number of repeats

我有一个包含大约 1500 万个整数 (int32) 的向量,其中包含大约 100 万个唯一值。我想找到一种有效的方法来计算重复的整数并将它们与原始向量相关联,这样我就有了一个包含每个元素计数的新向量。

这可能很清楚,所以这是我正在寻找的一个小例子:

A      = [1 1 1 3 2 5 2 1 2 6];
...
result = [4 4 4 1 3 1 3 4 3 1];

我的(不切实际的慢)实现如下(请注意,在我的 matlab 版本中,hist 不适用于整数):

A = randi(1e6,[15e6,1],'int32');
result = zeros(size(A),'int32');
[uniqueA,~,iuA] = unique(A);
counts = accumarray(iuA,1);

到目前为止一切顺利:uniqueA 包含 A 的唯一元素的列表,counts 包含每个元素对应数量的列表。这非常快。

接下来是慢的部分。我尝试了以下方法来检索每个元素的索引:

cellIndex = arrayfun(@(x) A == x, uniqueA,'UniformOutput',false);

但这会耗尽内存(使用 16 GB 内存)并在开始交换时停止运行。为了避免这种情况,我尝试遍历唯一元素(100 万),这也很慢:

for n = 1:length(uA)
    result(A == uA(n)) = counts(n);
end

不知道要等多久,因为等了半个小时还没做完

关于如何高效完成任务的任何想法?

一种方法-

[unq,~,idx] = unique(A);
out = changem(idx,histc(A,unq),1:max(idx))

样本运行-

>> A
A =
     1     1     1     3     2     5     2     1     2     6
>> [unq,~,idx] = unique(A);
>> changem(idx,histc(A,unq),1:max(idx))
ans =
     4     4     4     1     3     1     3     4     3     1

这是一个更简单的版本 -

[unq,~,idx] = unique(A);
counts = histc(A,unq);
out = counts(idx)

样本运行-

>> A
A =
     1     1     1     3     2     5     2     1     2     6
>> [unq,~,idx] = unique(A);
>> counts = histc(A,unq);
>> counts(idx)
ans =
     4     4     4     1     3     1     3     4     3     1