如何基于成员生日计算对应分组12个月区间的月度计数均值
实现方案
以下先提供你需要的循环实现写法,再附上性能更优的简便实现方案,两种方案都可以直接替换列名后运行。
前置预处理
无论用哪种方案,先统一把两个数据集的年月转换为pandas月周期类型,避免跨年跨月的计算错误:
import pandas as pd import numpy as np # 替换为你实际使用的列名即可 DF1['ym'] = pd.PeriodIndex(year=DF1['年份列'], month=DF1['月份列'], freq='M') DF2['birth_ym'] = pd.PeriodIndex(year=DF2['生日年'], month=DF2['生日月'], freq='M')
方法1:逐行循环实现
逻辑完全匹配需求描述,逐行处理DF2中的每位成员:
- 提取当前成员的分组ID、生日起始月份
- 生成从生日月开始的连续12个目标月份
- 从DF1中筛选同分组、月份在目标范围内的月度计数
- 计算均值存入结果列表,最后将列表作为新列追加到DF2
代码如下:
# 为DF1构建分组+月份的联合索引,大幅提升循环中的筛选速度 DF1_indexed = DF1.set_index(['分组ID', 'ym']).sort_index() mean_result = [] for _, row in DF2.iterrows(): current_gid = row['分组ID'] current_start_ym = row['birth_ym'] # 生成连续12个月的周期列表 target_months = [current_start_ym + offset for offset in range(12)] try: # 提取窗口内的计数值 window_counts = DF1_indexed.loc[current_gid].loc[target_months, '月度计数字段'].to_numpy() mean_val = window_counts.mean() except KeyError: # 若存在分组不匹配、月份缺失的情况,返回空值,可按需修改默认填充值 mean_val = np.nan mean_result.append(mean_val) DF2['生日起始12个月计数均值'] = mean_result
该写法优势是逻辑直白、调试方便,适合万级以内的小数据集;缺点是逐行遍历性能差,百万级数据下运行速度较慢
方法2:高性能简便实现(无显式逐行循环)
先预构建每个分组的有序月度计数序列,避免循环过程中反复筛选DF1,性能比纯循环写法高10~100倍,代码维护性更好:
# 预构建每个分组的有序月份、计数数组,仅需遍历一次DF1 group_cache = {} for gid, sub_df in DF1.groupby('分组ID'): sorted_sub = sub_df.sort_values('ym') group_cache[gid] = ( sorted_sub['ym'].to_numpy(), sorted_sub['月度计数字段'].to_numpy() ) def calc_window_mean(gid, start_ym): if gid not in group_cache: return np.nan ym_array, count_array = group_cache[gid] # 定位生日月在序列中的起始索引 start_pos = np.searchsorted(ym_array, start_ym) # 截取连续12个月的窗口计算均值 window_data = count_array[start_pos : start_pos + 12] return window_data.mean() if len(window_data) > 0 else np.nan # 批量计算所有成员的均值 DF2['生日起始12个月计数均值'] = DF2.apply(lambda x: calc_window_mean(x['分组ID'], x['birth_ym']), axis=1)
补充提示:如果DF1存在月度数据缺失,先执行下面的代码按分组补全所有月份,避免窗口长度不足12个月导致均值计算偏差:
DF1 = DF1.set_index('ym').groupby('分组ID')['月度计数字段'].resample('M').sum().reset_index()
如果DF1是完全连续无缺失的月度数据,还可以提前给每个分组预计算所有月份作为起始点的12个月滚动均值,直接通过表连接匹配结果,不需要使用apply,千万级数据也能秒级出结果。
内容的提问来源于stack exchange,提问作者Ananth Jason
相关产品推荐
相关产品推荐

