如何从分组Pandas DataFrame提取每组最小MAPE对应的模型?
提取每个商品-快照组合下MAPE最小的模型
问题背景
我有一个带多级索引(ord_base7商品标识、snapshot快照日期、model模型)的DataFrame,包含各模型的预测误差MAPE值。需要筛选出每个ord_base7/snapshot组合下MAPE最小的模型,而非全局最小值。
样本数据
import pandas as pd df_dict = {'ord_base7': ['100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K','100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K', '100179K'], 'snapshot': ['2020-12-31 00:00:00', '2020-12-31 00:00:00', '2020-12-31 00:00:00', '2020-12-31 00:00:00', '2020-12-31 00:00:00', '2020-12-31 00:00:00', '2020-12-31 00:00:00', '2021-01-31 00:00:00', '2021-01-31 00:00:00', '2021-01-31 00:00:00', '2021-01-31 00:00:00', '2021-01-31 00:00:00', '2021-01-31 00:00:00', '2021-01-31 00:00:00', '2021-02-28 00:00:00', '2021-02-28 00:00:00', '2021-02-28 00:00:00', '2021-02-28 00:00:00', '2021-02-28 00:00:00', '2021-02-28 00:00:00', '2021-02-28 00:00:00', '2021-03-31 00:00:00', '2021-03-31 00:00:00', '2021-03-31 00:00:00', '2021-03-31 00:00:00', '2021-03-31 00:00:00', '2021-03-31 00:00:00'], 'model': ['AutoArima', 'SARIMA', 'STLF', 'TESA', 'TESM', 'lstm_neural_net', 'prophet', 'AutoArima', 'SARIMA', 'STLF', 'TESA','TESM', 'lstm_neural_net', 'prophet', 'AutoArima', 'SARIMA', 'STLF', 'TESA', 'TESM', 'lstm_neural_net', 'prophet', 'AutoArima', 'SARIMA', 'STLF', 'TESA', 'TESM', 'lstm_neural_net'], 'MAPE': [71.50999999999999, 4439.13, 1.34, 96.31, 100.13000000000001, 70.17999999999999, 53.25, 18.32, 20227.11, 12.15, 92.25999999999999, 93.14, 12.2, 11.3, 8.99, 20664.37, 18.68, 15.8, 20.39, 1.69, 25.679999999999996, 3.0700000000000003, 8.68, 24.6, 5.43, 2.93, 1.87]} df = pd.DataFrame.from_dict(df_dict) df.set_index(['ord_base7', 'snapshot', 'model'],inplace = True)
解决方案
方法1:groupby + idxmin直接定位
按前两级索引分组,获取每组MAPE最小的行的完整索引,再用索引筛选原DataFrame:
# 获取每组MAPE最小的行的索引 min_mape_idx = df.groupby(level=['ord_base7', 'snapshot'])['MAPE'].idxmin() # 筛选结果 result = df.loc[min_mape_idx]
方法2:重置索引后分组排序
若不习惯多级索引操作,可先将索引转为普通列,分组后按MAPE升序排序取每组第一行:
# 重置索引 df_reset = df.reset_index() # 分组排序取最优模型 result = df_reset.sort_values('MAPE').groupby(['ord_base7', 'snapshot']).first().reset_index()
方法3:transform标记最小值行
用transform生成每组的最小MAPE值,通过布尔掩码筛选对应行:
# 生成每组最小MAPE的标记掩码 mask = df['MAPE'] == df.groupby(level=['ord_base7', 'snapshot'])['MAPE'].transform('min') # 筛选结果 result = df[mask]
结果示例
以样本数据为例,最终结果会包含:
2020-12-31快照下,STLF模型(MAPE=1.34)2021-01-31快照下,prophet模型(MAPE=11.3)2021-02-28快照下,lstm_neural_net模型(MAPE=1.69)2021-03-31快照下,lstm_neural_net模型(MAPE=1.87)
内容的提问来源于stack exchange,提问作者JordanBH
相关产品推荐
相关产品推荐

