问题:我有一个每日黄金价格的数据集。我想每个月取平均值,然后通过重新采样数据来做到这一点。接下来,我想将每个月的日期更改为每个工作月的结束,通过重新采样新的均值数据并再次采样来完成此操作。代码如下。
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
您可以通过将[BM]的
label
和
closed
设置为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())