多列分组+多条件行筛选:Pandas代码报错修复与需求实现
问题分析
报错ValueError: cannot insert date_freq, already exists是因为代码尝试向DataFrame插入已存在的date_freq列,属于重复操作导致的异常。以下是修正后的代码,同时实现需求中的数据筛选逻辑:
解决方案代码
首先确保date列为datetime类型,再按分组规则处理每个子数据集:
import pandas as pd # 确保日期列是datetime格式(若未转换则执行此步骤) df['date'] = pd.to_datetime(df['date']) def filter_group(group): freq = group['date_freq'].iloc[0] # 筛选actual_value数据 if freq == 'Q': # 按日期倒序取最近2个季度的actual_value actual_data = group[group['indicator'] == 'actual_value'].sort_values('date', ascending=False).head(2) # 获取这两个季度日期,再追加下一个季度日期作为mape的筛选范围 latest_dates = actual_data['date'] next_quarter = latest_dates.min() + pd.DateOffset(months=3) mape_target_dates = latest_dates.append(pd.Series(next_quarter)) else: # 月度数据处理 # 筛选指定时间段的actual_value actual_mask = (group['indicator'] == 'actual_value') & (group['date'] >= '2023-04-30') & (group['date'] <= '2023-07-31') actual_data = group[actual_mask] # 追加2023-08-31作为mape的额外筛选日期 mape_target_dates = actual_data['date'].append(pd.Series(pd.to_datetime('2023-08-31'))) # 筛选arima_mape和es_mape数据 mape_data = group[(group['indicator'].isin(['arima_mape', 'es_mape'])) & (group['date'].isin(mape_target_dates))] # 合并两类数据并返回 return pd.concat([actual_data, mape_data]) # 按指定维度分组并应用筛选逻辑 result_df = df.groupby(['indicator_name', 'region_code', 'date_freq'], group_keys=False).apply(filter_group) # 可选:重置索引 result_df = result_df.reset_index(drop=True)
关键修改说明
- 移除了原代码中重复插入
date_freq列的操作,直接从分组后的子集中读取该字段值,避免重复列报错。 - 针对季度/月度数据分别实现筛选逻辑:
- 季度数据通过倒序排序取最近2个季度,自动计算下一季度日期扩展mape筛选范围。
- 月度数据直接按指定时间区间筛选actual_value,手动追加目标日期扩展mape范围。
- 使用
group_keys=False避免分组键自动写入结果,保持数据结构简洁。
内容的提问来源于stack exchange,提问作者ah bon
相关产品推荐
相关产品推荐

