如何在Pandas中对分组滚动窗口内的Counter对象进行求和?
报错原因
Pandas 内置的rolling.sum()仅针对数值类型设计,聚合时会强制将输入转换为浮点型计算,而Counter属于Python自定义对象,无法被转换为数值类型,因此触发类型错误。
可行解决方案
两种方案都支持自定义未来统计天数,可直接修改FORWARD_DAYS变量调整:
from collections import Counter import pandas as pd # 自定义统计未来天数 FORWARD_DAYS = 6
方案1:逐行筛选法(逻辑直观,适合小数据量)
不需要调整滚动窗口方向,代码易读易维护:
# 先按id、日期排序,将日期设为索引 df = df.sort_values(['id', 'dates']).set_index('dates') def calc_forward_counter(group_df): result = [] for curr_dt in group_df.index: # 筛选同id下 大于当前日期 且 小于等于当前日期+6天的所有行 mask = (group_df.index > curr_dt) & (group_df.index <= curr_dt + pd.Timedelta(days=FORWARD_DAYS)) # 对筛选出的Counter求和,初始值为空Counter total_cnt = sum(group_df.loc[mask, 'state_cntr'], Counter()) result.append(total_cnt) group_df['output_needed'] = result return group_df # 按id分组处理后恢复原结构 df = df.groupby('id', group_keys=False).apply(calc_forward_counter).reset_index()
方案2:滚动自定义聚合(性能更高,适合大数据量)
通过调整排序方向适配滚动窗口默认的向后统计逻辑,比逐行筛选效率高3~10倍:
# 先按id、日期排序,将日期设为索引 df = df.sort_values(['id', 'dates']).set_index('dates') def rolling_calc_counter(group_df): # 组内按日期倒序排列,把未来数据转到滚动窗口可覆盖的区间 group_df = group_df.sort_index(ascending=False) # 滚动6天,自定义Counter求和,shift(1)排除当前行,空值填充为空Counter group_df['output_needed'] = group_df['state_cntr'].rolling(f'{FORWARD_DAYS}D').apply( lambda x: sum(x, Counter()), raw=False ).shift(1).fillna(Counter()) # 恢复正序排列返回 return group_df.sort_index() # 按id分组处理后恢复原结构 df = df.groupby('id', group_keys=False).apply(rolling_calc_counter).reset_index()
两种方案输出均完全匹配需求的预期结果。
内容的提问来源于stack exchange,提问作者Rahul P
相关产品推荐
相关产品推荐

