pandas 中重采样函数背后的直觉

Intuition behind resample function in pandas

问题:我有一组每日黄金价格。我想取每个月的平均值,并通过对数据重新采样来完成。接下来,我想将每个月的日期更改为每个业务月的月底,我通过重新采样新的平均数据并再次重新采样来完成此操作。代码如下

gold_df = gold_df.resample(rule='M').mean()
gold_df = gold_df.resample(rule='BM').last()

>>> gold_df
Date    
1979-01-31  227.215217
1979-02-28  245.670000
1979-03-30  NaN
1979-04-30  238.664286
1979-05-31  257.782609

问题:但是,我在某些月份得到了 NaN。在这种情况下,重采样方法不应该只更改日期,因为每个月只有一个值(由于第一个重采样步骤)。我通过执行以下操作解决了这个问题,但在理解 resample() 背后的直觉以及为什么我需要首先以 'BMS' 频率然后再次 'BM' 重新采样时感到困惑。

gold_df = gold_df.resample(rule='M').mean()
gold_df = gold_df.resample(rule='BMS').last()
gold_df = gold_df.resample(rule='BM').last()

>>> gold_df
Date    
1978-12-29  226.000000
1979-01-31  227.215217
1979-02-28  245.670000
1979-03-30  242.047727
1979-04-30  238.664286

这与您数据中的缺失值无关。 NaN 当月的最后一天不是工作日时出现在这里。

看下面的例子:

idx = pd.date_range('2020-01-01','2020-12-31')
s = pd.Series(pd.np.random.randint(20, 30, len(idx)), index=idx)
s.resample('M').mean().resample('BM').last().to_frame().assign(day=s.resample('M').mean().index.day_name())
#                    0        day
#2020-01-31  24.612903     Friday
#2020-02-28        NaN   Saturday
#2020-03-31  24.096774    Tuesday
#2020-04-30  24.433333   Thursday
#2020-05-29        NaN     Sunday
#2020-06-30  23.800000    Tuesday
#2020-07-31  23.677419     Friday
#2020-08-31  23.870968     Monday
#2020-09-30  25.333333  Wednesday
#2020-10-30        NaN   Saturday
#2020-11-30  24.266667     Monday
#2020-12-31  23.806452   Thursday

您可以通过将 label closed 设置为 'BM' 的 left 来规避此问题(默认为正确):

s.resample('M').mean().resample('BM', label='left', closed='left').last()
#2020-01-31    24.612903
#2020-02-28    23.896552
#2020-03-31    24.096774
#2020-04-30    24.433333
#2020-05-29    24.064516
#2020-06-30    23.800000
#2020-07-31    23.677419
#2020-08-31    23.870968
#2020-09-30    25.333333
#2020-10-30    24.838710
#2020-11-30    24.266667
#2020-12-31    23.806452
#Freq: BM, dtype: float64
assert all(s.resample('M').mean().resample('BM', label='left', closed='left').last() == s.resample('M').mean().resample('BMS').last().resample('BM').last())