如何在DataFrame重采样周期中获取极值及其对应发生日期?
问题描述
我有一个以datetime为索引、仅包含资产价格列的DataFrame,示例如下:
asset_value date 2023-05-30 136.57000000 2023-05-31 133.30000000 2023-06-01 134.83000000 2023-06-02 134.63000000 2023-06-05 133.73000000
数据跨度数年,我希望按不同周期(比如周)对DataFrame重采样,计算周期内的min()和max()值,用以下代码可以实现:
df.resample("W").agg({'asset_value': ["min", "max"]})
返回结果如下:
asset_value min max date 2023-06-04 133.300000 136.570000 2023-06-11 133.730000 136.200000 2023-06-18 138.930000 141.790000 2023-06-25 136.070000 138.920000 2023-07-02 139.800000 146.550000
但这个结果只返回了区间极值和区间右边界日期,我还想知道这些极值对应的具体发生日期。
我尝试过在原DataFrame中添加额外列(星期几、日、月、年),但没成功,代码如下:
# 确保索引是datetime类型 df.index = pd.to_datetime(df.index) df.reset_index(inplace=True) # 添加星期几、日、月、年列 df['day_of_week'] = df['date'].dt.dayofweek df['day_of_month'] = df['date'].dt.day df['month'] = df['date'].dt.month df['year'] = df['date'].dt.year # 重新设置datetime索引并删除date列 df.set_index(df['date'], inplace=True) df.drop(['date'], axis=1, inplace=True)
解决方案
要获取极值对应的日期,直接利用pandas的idxmin和idxmax方法即可,这两个方法会返回极值对应的原索引(即日期),无需额外添加日期列。
方法1:直接扩展聚合函数列表
修改重采样的agg参数,同时计算极值和对应的日期,之后再整理列名让结果更直观:
# 确保索引是datetime类型(若未处理) df.index = pd.to_datetime(df.index) # 按周重采样,同时计算极值及对应日期 result = df.resample("W").agg({ 'asset_value': ['min', 'max', 'idxmin', 'idxmax'] }) # 扁平化多级列名 result.columns = ['min_value', 'max_value', 'min_date', 'max_date'] # 可选:将重采样的区间日期转为普通列 result.reset_index(inplace=True)
执行后会得到类似这样的结果:
date min_value max_value min_date max_date 0 2023-06-04 133.300 136.570 2023-05-31 2023-05-30 1 2023-06-11 133.730 136.200 2023-06-05 2023-06-XX ...
方法2:自定义聚合函数(处理特殊场景)
如果需要处理极值重复的情况(比如同一个周期内多次出现相同极值),可以自定义聚合函数来获取所有极值日期:
def get_min_info(series): min_val = series.min() # 获取所有出现最小值的日期,转为逗号分隔的字符串 min_dates = ','.join(series[series == min_val].index.strftime('%Y-%m-%d')) return pd.Series([min_val, min_dates], index=['min_value', 'min_dates']) def get_max_info(series): max_val = series.max() max_dates = ','.join(series[series == max_val].index.strftime('%Y-%m-%d')) return pd.Series([max_val, max_dates], index=['max_value', 'max_dates']) # 按周重采样 result = df.resample("W").agg({ 'asset_value': [get_min_info, get_max_info] }) # 扁平化多级列名 result.columns = result.columns.map('_'.join) result.reset_index(inplace=True)
这种方式可以返回周期内所有出现极值的日期,适合需要完整记录极值出现时间的场景。
注意事项
idxmin和idxmax默认返回第一个出现极值的日期,若需要所有极值日期,参考方法2的自定义函数逻辑即可。- 确保原DataFrame的索引是datetime类型,否则
idxmin/idxmax无法返回正确的日期信息。
内容的提问来源于stack exchange,提问作者Jay Murphy
相关产品推荐
相关产品推荐

