基于当前行值筛选DataFrame子集并求和生成新列的问题
问题:按行对应年份计算列总和出错
示例DataFrame
# Create a sample dataframe df = pd.DataFrame({'num_posts': [4, 6, 3, 9, 1, 14, 2, 5, 7, 2,12], 'date' : ['2020-03-01', '2020-01-02', '2020-01-03', '2020-01-04', '2019-01-05', '2019-01-06', '2020-01-07', '2020-01-08', '2020-01-09', '2020-01-10','2020-01-11']}) cols=['num_posts']
需求与现有问题
需要生成诸如“上一年最后一周num_posts总和”“上一年最后一周与上月总和的比值”这类时间维度聚合特征。当前尝试计算每行对应年份的num_posts总和,但代码未正确筛选同年份子集,所有行都返回了整个DataFrame的总和65。
现有日期处理函数:
def create_calendar_columns(df,dt): df['day_number']= pd.to_datetime(df[dt]).dt.dayofyear df['week_number']= pd.to_datetime(df[dt]).dt.isocalendar().week df['year']= pd.to_datetime(df[dt]).dt.year return df
现有求和函数:
def calculate_curr_year_sum(df,cols,dt): df=create_calendar_columns(df,dt) df[dt]=pd.to_datetime(df[dt]) for col in cols: df['curr_year_sum_'+str(col)]= df.loc[df['year']==df[dt].dt.year,col].sum() # 预期:计算与当前行年份相同的所有行的col总和
错误原因
代码中df['year']==df[dt].dt.year是整列的布尔比较,最终筛选出的是所有年份等于当前整个df的date列年份集合的行(实际这里date列包含2019和2020,所以该条件会匹配所有行),sum操作得到的是全局总和,没有按每行的年份单独分组计算。
解决方案
使用groupby结合transform方法,transform会将分组聚合后的结果广播回原DataFrame的每一行,正好匹配每行对应年份的总和需求。
修改后的calculate_curr_year_sum函数:
def calculate_curr_year_sum(df, cols, dt): df = create_calendar_columns(df, dt) # 避免重复转换日期(create_calendar_columns里已处理) for col in cols: # 按year分组,对col求和后广播到每行 df[f'curr_year_sum_{col}'] = df.groupby('year')[col].transform('sum')
运行后,2019年的行对应的curr_year_sum_num_posts为1+14=15,2020年的行对应的总和为4+6+3+9+2+5+7+2+12=50,符合预期。
扩展到其他时间特征
如果要实现“上一年最后一周总和”这类特征,可以按以下思路:
- 先按
year和week_number分组,计算每周总和 - 对每个年份,找到最大的
week_number对应的值,作为该年最后一周总和 - 将上一年的最后一周总和匹配到当前年份的所有行
示例代码片段:
# 计算每周总和 df['weekly_sum'] = df.groupby(['year', 'week_number'])['num_posts'].transform('sum') # 获取每年最后一周的总和 year_last_week_sum = df.groupby('year').apply( lambda x: x[x['week_number'] == x['week_number'].max()]['weekly_sum'].iloc[0] ).reset_index(name='last_week_sum') # 匹配上一年的最后一周总和到当前行 df['prev_year_last_week_sum'] = df['year'].map(year_last_week_sum.set_index('year')['last_week_sum'].shift(1))
内容的提问来源于stack exchange,提问作者user3585510
相关产品推荐
相关产品推荐

