合并多个平均值而不计算总计

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了合并多个平均值而不计算总计相关的知识,希望对你有一定的参考价值。

我目前有来自序列化数据的多个[Average, Count]对。用户希望能够将一些值集合(分组)在一起并获得聚合结果。

我很喜欢它,我会做Sum(Average * Count) / Sum(Count)

但问题是,有些值非常大,如果我总结它们会导致算术溢出。

有没有办法合并平均部分而不计算总数?计数部分非常明显。

答案

假设CountAverage是索引值,您可以通过这种方式计算聚合平均值:

TotalCount = Sum(Count)
TotalAverage = Sum(Average * (Count/TotalCount))

如果要在序列化数据的单次迭代中计算值,则可以以看起来像指数平均值的方式对连续加权平均值求和。

TotalCount = 0
TotalAverage = 0
for each index in data-set of [Average, Count]
    TotalCount = TotalCount + Count[index]
    Weight = Count[index]/TotalCount
    TotalAverage =   TotalAverage * (1 - Weight)
                   + Average[index] * Weight

您可以通过考虑前两对来推导出正确的方法。

如果只有第一对:

TotalCount = Count[1]
TotalAverage = Average[1]

但是,如果有两对:

TotalCount = Count[1] + Count[2]
TotalAverage =   Average[1] * (Count[1]/TotalCount) 
               + Average[2] * (Count[2]/TotalCount)

如果我们从第一对迭代到第二对,那么两对计算可能如下所示:

TotalCount = TotalCount + Count[2]
TotalAverage =   TotalAverage * (TotalCount - Count[2])/TotalCount
               + Average[2]   * (Count[2]/TotalCount)

如果我们让Weight代表Count[2]/TotalCount,上面简化为:

TotalCount = TotalCount + Count[2]
Weight = Count[2]/TotalCount
TotalAverage =   TotalAverage * (1 - Weight)
               + Average[2] * Weight

由于TotalCountTotalAverage在采用一对新的序列化数据的每一步都是正确的,因此[2]可以用迭代索引替换。

另一答案

虽然@jxh的答案很好并且解决了你的问题,但是他和你的原始方法对成对数据进行了两次传递(首先是总计数,然后是平均值),这可能会损害性能。你可以一次完成,进行滚动平均。即使对来自流,也可以使用它,你不知道它们中有多少

一些Python代码:

data = [(3.1, 12), (5.2, 17), (9.7, 11)]

total_count = 0
total_avg   = 0.0
for avg, count in data:
    n0 = total_count
    total_count += count

    p = float(n0) / float(total_count)
    total_avg = p*total_avg + (1.0 - p)*avg

print(total_count)
print(total_avg)

以上是关于合并多个平均值而不计算总计的主要内容,如果未能解决你的问题,请参考以下文章

对总计超过200万条记录(行)的多个输入文件(固定空格分隔的42列txt文件)进行合并排序和合并

如何修改 s-s-rS 矩阵报表以显示总计的平均值?

如何在 SwiftUI 中计算数组的总计、小计和平均值

Python代码阅读(第19篇):合并多个字典

如何组合绑定片段而不将它们包装在 XML 文字中

MySQL 数据底部出现总计字样 第二种办法 纵向合并 20161103