是否有启发式的groupBy + count算法?

时间:2018-11-14 16:46:08

标签: algorithm group-by language-agnostic

我有一个整数列表,我想计算每个整数在列表中出现的次数。

例如:[0,5,0,1,3,3,1,1,1]给出(0 -> 2), (1 -> 4), (3 -> 2), (5 -> 1)。我只需要计数,而不是值(目标是获得计数的直方图)。

一种常见的方法是按值分组,然后计算每个集合的基数。在SQL中:SELECT count(*) FROM myTable GROUPBY theColumnContainingIntegers

有更快的方法吗?启发式或概率式的方法很好,因为我正在计算大型数据集,而牺牲精度可以提高速度。

类似于HyperLogLog算法(用于计算数据集中不同元素的数量)的东西会很棒,但是我没有找到类似的东西...

1 个答案:

答案 0 :(得分:1)

让我们将包含9个元素[0,5,0,1,3,3,1,1,1]的集合设为大,但元素的频率相同:

> bigarray = [0,5,0,1,3,3,1,1,1] * 200
 => [0, 5, 0, 1, 3, 3, 1, 1, 1, 0, 5, 0, 1, 3, 3, 1, ...

现在bigarray的大小是1800,所以让我们尝试使用它。

抽取180个元素的样本(此集合中随机包含180个元素)

此随机子集的计算发生率

{5=>19, 3=>45, 1=>76, 0=>40}

归一化:

{5=>1.0, 3=>2.3684210526315788, 1=>4.0, 0=>2.1052631578947367}

当然对于不同的随机子集结果会有所不同:

{5=>21, 3=>38, 1=>86, 0=>35}

归一化

{5=>1.0, 3=>1.8095238095238095, 1=>4.095238095238095, 0=>1.6666666666666667}

当然那里有一些错误-这是不可避免的,您将需要说明什么是可以接受的错误

现在对50%的0和1的50%的bigarray(大小为1000)进行相同的测试

 > bigarray = [0,1] * 500
 => [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,  ...

具有100个元素的样本:

{0=>50, 1=>50}

归一化

{0=>1.0, 1=>1.0}

第二个样本:

{0=>49, 1=>51}

归一化

{0=>1.0, 1=>1.0408163265306123}

似乎我们可以轻松地减少子集,Sampling来了。

尤其是Reservoir Sampling-如果您的数据“实时”填充或设置的数据太大而无法一次处理所有值,这可能非常有用。

修改

关于评论: 当然,如果集合很大并且某些元素很少出现,那么您可能会丢失它,并且出现的次数等于0。

然后,您可以使用某种平滑功能(选中additive smoothing)。只需假设每个可能的元素比实际出现的时间多出1倍即可。

例如,假设我们已设置:

1000 elements 1
100 elements 2
10 elements 3
1 elements 4

假设我们的子集包含{1 => 100,2 => 10,3 => 1,4 => 0}

平滑参数= 0.05,因此每次出现时我们加0.05

{1 => 100.05,2 => 10.05,3 => 1.05,4 => 0.05}

当然,这是假设您知道该集中甚至可能存在哪些值。