【问题标题】:Is there a heuristic algorithm for groupBy + count?groupBy + count 有启发式算法吗?
【发布时间】:2018-11-14 16:46:07
【问题描述】:

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

例如:[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 算法(用于计算数据集中不同元素的数量)的东西会很棒,但我没有找到类似的东西......

【问题讨论】:

    标签: algorithm group-by language-agnostic


    【解决方案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 和 50% 的 1 对 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}

    当然,这是假设您知道集合中可能出现的值。

    【讨论】:

    • 我已经尝试过采样,但这仅适用于每个不同元素在数组中出现足够多次的情况。当您通过仅计算 n*p 元素(其中 p 是 0 和 1 之间的比例)对 n 元素的数组进行采样时,您得到的概率约为 (1-p)**k 没有检测到出现 @987654340 的元素@次(如果n>>k)。
    • 如果您尝试拥有至少数百万个元素的数组(如果您需要采样就是这种情况),您将无法检测到这些元素的一部分。这可能会产生问题,因为您会失去元素多样性中不可忽略的一部分。
    • 我尝试结合采样来估计循环元素,并使用 hyperLogLog 来估计不同元素的基数(这让我粗略估计了我没有检测到多少不同元素)。问题是,如果运气不好,未检测到的元素可能会出现 1 次或 100 次甚至更多次。
    • 因此采样只有在接近 100% 的情况下才足够准确,这样就有点没用了。
    • 更新了我的答案,考虑使用平滑
    猜你喜欢
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    相关资源
    最近更新 更多