使用指定公式按日聚合pandas DataFrame的用户每日指标值
问题描述
现有如下结构的pandas DataFrame:
import pandas as pd data = { 'id': [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3], 'datetime': ['2021-03-15', '2021-03-15', '2021-03-17', '2021-03-17', '2021-03-12', '2021-03-12', '2021-12-14', '2021-04-07', '2021-07-09', '2021-04-25', '2021-04-25'], 'n': [1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2], 't': [1.41, 1.05, 2.01, 0.79, 1.37, 2.19, 1.28, 1.9, 0.97, 1.48, 1.96], 'leq': [73.95284344, 75.08732477, 42.52073186, 14.16069694, 59.36296547, 48.7827182, 44.48691532, 63.63032644, 95.20787662, 61.38061937, 12.50041565] } df = pd.DataFrame(data)
需要使用指定聚合公式,为每个用户生成按日期维度聚合的每日指标值:
当前遇到的问题是每个日期分组下对应的n值条目数量不固定,需要适配任意分组长度完成聚合计算。
实现方法
公式逻辑为以t为权重的leq加权平均值:对同一id+datetime分组,计算所有行t*leq的和,再除以该分组所有t值的和。pandas的groupby原生支持任意长度的分组聚合,不需要手动判断每个分组的条目数量。
方法1:apply 自定义聚合(代码简洁)
直接在分组后传入自定义计算逻辑即可:
result = df.groupby(['id', 'datetime'], as_index=False).apply( lambda group: pd.Series({ 'daily_metric': (group['t'] * group['leq']).sum() / group['t'].sum() }) )
方法2:agg 聚合(性能更高,适合大数据量)
先预计算乘积列,再用内置聚合函数减少开销:
# 预计算t和leq的乘积 df['t_leq_product'] = df['t'] * df['leq'] # 分组聚合求和 agg_df = df.groupby(['id', 'datetime'], as_index=False).agg( total_t=('t', 'sum'), total_t_leq=('t_leq_product', 'sum') ) # 计算最终指标 agg_df['daily_metric'] = agg_df['total_t_leq'] / agg_df['total_t'] # 清理临时列得到最终结果 result = agg_df.drop(columns=['total_t', 'total_t_leq'])
计算结果
两种方法得到的结果一致,如下:
id datetime daily_metric 0 1 2021-03-15 74.437051 1 1 2021-03-17 28.657920 2 2 2021-03-12 52.864671 3 2 2021-12-14 44.486915 4 3 2021-04-07 63.630326 5 3 2021-04-25 33.459146 6 3 2021-07-09 95.207877
- 仅含1条记录的分组(如id=3、2021-04-07),计算结果和原行
leq值一致,符合公式逻辑 - 含多条记录的分组自动完成加权计算,不需要额外适配行数
内容的提问来源于stack exchange,提问作者Stephen Okiya
相关产品推荐
相关产品推荐

