使用pandas shift(periods=1, freq='ME')出现日期偏移错误的原因咨询
为什么pandas的shift(freq='ME')结果和预期不符?
运行代码
import pandas as pd d = [ {'Date Enrolled': pd.Timestamp('2013-11-30'), 'metric': 2}, {'Date Enrolled': pd.Timestamp('2013-12-01'), 'metric': 0}, {'Date Enrolled': pd.Timestamp('2013-12-02'), 'metric': 0}, {'Date Enrolled': pd.Timestamp('2013-12-03'), 'metric': 0}, {'Date Enrolled': pd.Timestamp('2013-12-04'), 'metric': 0}, {'Date Enrolled': pd.Timestamp('2013-12-05'), 'metric': 0} ] tdf = pd.DataFrame(d) tdf = tdf.set_index(['Date Enrolled']).asfreq('D') tdf['metric'].shift(periods=1, freq='ME')
实际运行结果
Date Enrolled 2013-12-31 2 2013-12-31 0 2013-12-31 0 2013-12-31 0 2013-12-31 0 2013-12-31 0 Name: metric, dtype: int64
预期结果
Date Enrolled 2013-12-31 2 2014-01-31 0 2014-01-31 0 2014-01-31 0 2014-01-31 0 2014-01-31 0 Name: metric, dtype: int64
原因解释
问题出在freq='ME'的偏移逻辑上:
ME对应pd.offsets.MonthEnd偏移量,它的行为是返回不早于当前日期的下一个月末日期。- 对于
2013-11-30(11月月末),下一个月末是2013-12-31; - 对于
2013-12-01至2013-12-05这些12月内的日期,它们的下一个月末就是当月的月末2013-12-31。
所以所有日期经过shift(periods=1, freq='ME')处理后,都会指向2013-12-31,这就是实际结果和预期不符的核心原因。
- 对于
如果你想实现「将原日期所在月份向后推1个月,再取该月月末」的逻辑,可以用以下方式:
# 方法1:通过周期转换实现 result = tdf['metric'] result.index = result.index.to_period('M').shift(1).dt.to_timestamp(how='end') print(result) # 方法2:结合DateOffset和MonthEnd result = tdf['metric'].shift(periods=1, freq=pd.DateOffset(months=1)) result.index = result.index + pd.offsets.MonthEnd(0) print(result)
这两种方法都会得到你预期的结果。
内容的提问来源于stack exchange,提问作者Jamie Marshall
相关产品推荐
相关产品推荐

