如何按2年间隔计算DataFrame中Parts_needed的累积和?
解决按2年月份周期计算Parts_needed累积和的问题
看起来你需要的是基于月份周期的滚动2年累积和——每个月的Parts_needed会持续计入接下来24个月的总和,直到刚好满2年的次月就不再计入。这种带时间窗口的累积确实没法直接用np.cumsum()实现,下面给你两种可行的方案,分别适合大数据量和小数据集场景:
方案一:向量化实现(高效,适合大数据)
核心思路是用矩阵广播快速判断每个Parts_needed值的生效时间范围,然后计算对应范围内的总和:
import pandas as pd # 1. 先把Year和Month合并为标准日期列,方便时间计算 dfgg['date'] = pd.to_datetime(dfgg[['Year', 'Month']].assign(Day=1)) # 2. 按PartId分组计算(假设每个PartId需要单独统计,若不需要可去掉groupby) cumulative_results = [] for part_id, group in dfgg.groupby('PartId'): # 确保组内数据按日期排序 sorted_group = group.sort_values('date').reset_index(drop=True) # 生成两个布尔矩阵: # - date_matrix:判断当前行的日期是否早于等于目标行的日期(确保是历史数据) date_matrix = sorted_group['date'].values[:, None] <= sorted_group['date'].values # - end_date_matrix:判断当前行日期+2年是否晚于目标行日期(确保还在生效期内) end_dates = sorted_group['date'] + pd.DateOffset(years=2) end_date_matrix = end_dates.values[:, None] > sorted_group['date'].values # 两个矩阵取交集,得到每个值的生效范围 valid_mask = date_matrix & end_date_matrix # 计算每行的累积和:用矩阵乘法快速求和 sorted_group['cum_parts'] = sorted_group['Parts_needed'].values @ valid_mask cumulative_results.append(sorted_group) # 合并结果并恢复原索引顺序 dfgg = pd.concat(cumulative_results).sort_index()
方案二:Apply实现(直观,适合小数据)
如果你的数据集不大,用apply写逻辑会更易懂,每一步都能清晰看到筛选规则:
import pandas as pd # 1. 同样先创建日期列 dfgg['date'] = pd.to_datetime(dfgg[['Year', 'Month']].assign(Day=1)) # 2. 定义计算单一行累积和的函数 def get_cumulative_sum(row, group_data): # 筛选条件:当前行的日期 >= 历史行日期,且历史行日期+2年 > 当前行日期 valid_entries = group_data[ (group_data['date'] <= row['date']) & ((group_data['date'] + pd.DateOffset(years=2)) > row['date']) ] return valid_entries['Parts_needed'].sum() # 3. 按PartId分组,对每行应用函数计算累积和 dfgg['cum_parts'] = dfgg.groupby('PartId').apply( lambda g: g.apply(get_cumulative_sum, group_data=g) ).reset_index(drop=True)
验证你的示例场景
以你提到的2020年2月为例:
- 2018年1月的
72,它的生效结束日期是2020年1月,所以2020年2月的日期(2020-02-01)超过了这个结束日期,会被排除在求和范围外 - 此时累积和就是之前的总和(2328)加上当月的
45,再减去到期的72,和你的预期完全一致
内容的提问来源于stack exchange,提问作者IndigoChild
相关产品推荐
相关产品推荐

