分组均值不能直接再平均:用sum与count合并统计结果
作者:lgbisha。本文由AI辅助撰写、代码生成与校对,数据均为合成样例。本机实际执行了30项算术与边界断言,30通过、0失败;没有使用真实公司报表,也不声称完成云端部署、认证考试或端到端Agent开发。
报表已经算出各组平均值,汇总时再求一次平均,看起来很自然。但“每个组拥有相同权重”和“每条有效观察拥有相同权重”是两个不同的问题。只保留一列平均值,经常不足以正确重建总体结果。
本文用Python标准库和精确分数构造可重放的例子,重点不是增加统计公式,而是保留足够的汇总信息,避免数据跨分区、跨批次流转以后失去分母。
一、55和82都能算出来,但回答的问题不同
构造两个互不重叠、同一单位的数值组:
| 组 | 数据 | 有效观察数 | 总和 | 组内均值 |
|---|---|---|---|---|
| A | 10、10 | 2 | 20 | 10 |
| B | 八个100 | 8 | 800 | 100 |
如果把两组的均值直接平均,结果是 (10 + 100) / 2 = 55。这相当于让A组和B组各占一半权重,回答的是“两个组均值的等权平均”。
如果要计算全部十条观察的均值,结果应为 (20 + 800) / (2 + 8) = 82。等价地,可以按有效观察数对组均值加权:(10 × 2 + 100 × 8) / 10 = 82。
因此,55不是一个算术错误,而是不一定符合当前汇总目标。只有组内有效观察数相同等特定条件下,简单平均组均值才自然对应总体的等权观察均值。若业务本来要求各组等权,则不应擅自改成按观察数加权。
二、把sum和count一起带到下游
对于同一数值指标的算术均值,一个简洁的可合并摘要是:
from fractions import Fraction
def summarize(values):
observed = [value for value in values if value is not None]
return {"sum": sum(observed), "count": len(observed)}
def merge_summaries(summaries):
return {
"sum": sum(summary["sum"] for summary in summaries),
"count": sum(summary["count"] for summary in summaries),
}
def summary_mean(summary):
if summary["count"] == 0:
return None
return Fraction(summary["sum"], summary["count"])
groups = [summarize([10, 10]), summarize([100] * 8)]
print(summary_mean(merge_summaries(groups)))
输出为 82。这里使用整数输入和 Fraction,是为了让教学样例用精确等式复核,避免把浮点舍入误差和统计口径差异混为一谈。
这段代码不是通用生产聚合库:示例只约定整数和代表缺失的 None,没有实现任意CSV解析、NaN、无穷值、跨币种换算、去重或恶意输入校验。实际系统需要按数据协议处理这些边界。
三、权重是有效数,不一定是表格行数
再看一组容易忽略的输入:A组为 [10, None, None],B组为 [100]。若约定跳过未采集值,两组分别只有1条有效观察,总体均值为 (10 + 100) / 2 = 55。
如果误把A组的三行都当成有效权重,就会算成 (10 × 3 + 100) / 4 = 32.5。这并不是正确的跳过缺失汇总结果:它把A组已观测到的10赋予了额外权重。
同时,数值0是一条有效观察,不能用 if value 过滤,否则会把0也删掉。这里明确使用 value is not None。
全缺失组的摘要可以是 sum=0, count=0,但其均值应保持未知,而不是变成0。合并一个空组不改变非空组的均值;如果所有组都为空,最终仍返回 None。只看总和为0,无法区分“没有观察”与“观察值确实合计为0”。
四、合并百分比时,要保留分子与分母
合成验收例子中,A组通过1项、共2项,比例为50%;B组通过8项、共8项,比例为100%。两个比例简单平均得到75%,而全部项目的通过比例为 (1 + 8) / (2 + 8) = 90%。
如果目标是“全部项目的通过比例”,应累计通过数与项目数,而不是只保存格式化后的百分比。这个例子只说明算术合并,不代表任何真实产品的性能或实验成功率。
还要核对分母是否具有相同含义。例如按请求数、按用户数和按天数统计的比例,不能只因为都是百分比就直接混合;分子是否去重、统计窗口是否相同,也要先确定。
五、不要用展示用的四舍五入均值反推总和
若A组为 [0, 0, 1],B组为 [1],精确总体均值为 2 / 4 = 0.5。A组均值展示为0.33后,再按数量加权,会得到 (0.33 × 3 + 1) / 4 = 0.4975。
这次差异来自展示值已丢失精度。保留原始总和1、有效数3,再合并B组的总和1、有效数1,就无需通过近似均值还原总和。
这里不主张所有指标都能只靠sum和count合并。分位数、中位数、去重人数等有各自的状态与合并方法,不能套用均值摘要。即便是均值,批次重复、分组重叠或单位不一致,也会使简单合并失去正确业务含义。
六、实际验证了哪些边界
本次在Python 3.12.3运行独立脚本,30项断言全部通过,覆盖:两组总和与计数、55与82的区别、等样本量情形、缺失值权重、零值、全缺失、空组合并、不同分区方式的一致性、组顺序不变性、比例合并,以及提前舍入造成的信息损失。
这些是本地小样本的确定性验证,不是对统计库的全面测试,也不是云实验评分。使用精确整数和分数,是为了让期望值有独立算术依据,而不是看到某个输出后再改答案。
结语
汇总之前先问:本次是让每个组等权,还是让每条有效观察等权?如果目标是后者,平均值旁边应该保留对应的总和与有效计数。把分母作为数据契约的一部分,比在报表最后再猜权重更可靠。
参考:Python官方文档 statistics.mean 与 fractions.Fraction。示例的聚合方法是常规统计知识,不主张算法原创;本文的可复核贡献是上述合成对照、明确的合并前提与实际运行的30项检查。
- Python官方标准库手册:statistics — Mathematical statistics functions,mean小节。
- Python官方标准库手册:fractions — Rational numbers。
- 点赞
- 收藏
- 关注作者
评论(0)