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