本文介绍如何使用 pandas `transform` 方法直接在原数据框中高效计算每组内某列唯一值的平均数,并将结果广播回原始行,避免显式去重、新建 dataframe 和冗余合并操作。
在数据分析实践中,常需基于业务逻辑对“去重后”的数值进行聚合(如:每位用户各品类下出现过的独立计数值的均值),再将该统计量广播到原始明细表的每一行,用于后续归一化、特征工程或指标对比。传统做法(如先 drop_duplicates 再 merge)虽可行,但存在冗余计算、内存开销大、代码可读性差等问题。
核心优化思路是:不真正删除重复行,而是在 groupby 时对每组内 counts 的唯一值先行去重,再求均值——这可通过 groupby(…).apply(lambda x: x.unique().mean()) 实现;但更简洁、向量化且符合 transform 语义的方式,是利用 groupby(…).transform() 配合自定义聚合函数。
然而需注意:原始问题描述与示例代码存在关键偏差——其目标实为 “每个 user_id 组内 counts 的平均值” 和 “每个 (user_id, Category) 组内 counts 的平均值”,而非严格意义上的“unique values 的平均”。观察示例输出:
- Overall_average__Unique_Counts = 1.83 实为全部 counts 值(1,2,2,2,2,2,3,3,3)的均值 ≈ 2.09?但实际是 df1_unique[‘counts’].mean() = (3+2+1+2+1+2+2+2)/8 = 1.875 ≈ 1.83(四舍五入),即对去重后组合 (user_id, Category, counts) 的 counts 求全局均值;
- Categorywise_average_Unique_counts 中 ABC→2.00 来自 {3,2,1} 去重后均值?但 ABC 对应 counts=[3,3,3,2,2,1] → 唯一值 {1,2,3} → 均值=2;XYZ 对应 [2,1,2,2,2] → 唯一值 {1,2} → 均值=1.5,但输出为 1.67,说明实际计算的是 df1_unique.groupby(‘Category’)[‘counts’].mean(),即仅对去重后的样本求均值,而非每组内动态去重。
因此,若严格按“每组内 counts 的唯一值均值”需求,正确解法如下: