熊猫,.resample的意外行为(' B')

时间:2016-05-20 08:46:55

标签: python pandas resampling

我从每月系列的时间戳开始,作为月底。我想通过填充前向值将它们上传到商业(周一至周五)每日频率。 我希望有两个条件成立:

  1. 如果是原版的周末,再也不会丢失重新取样的值 时间序列
  2. 始终向前填充:如果原始系列中的EOM日期是 星期六,我希望这个观察出现在下周一 每日系列
  3. 虽然不优雅,但我得出结论,最安全的方法是:

        daily_series = monthly_series.resample(rule='D').ffill().resample(rule='B',how='first')
    

    现在,出乎意料的是:

        dates = ['1953-02-28', '1953-03-31', '1953-04-30', '1953-05-31']
        # '1953-02-28' was a Saturday
    
        values = [1,2,3,4]
        monthly_ts  = pd.Series(values, index = dates)
    
        monthly_ts
        Out[74]: 
        1953-02-28    1
        1953-03-31    2
        1953-04-30    3
        1953-05-31    4
        dtype: int64
    
        daily_ts = monthly_ts.resample(rule='D').ffill().resample(rule='B',how='first')
    
         Out[77]: 
         1953-02-27    1           # Why do I have this observation?
         1953-03-02    1
         1953-03-03    1
         1953-03-04    1
    

    星期六的观察结果在星期五用于重新取样。 这发生在.resample(rule =' B')

    之后

    您能否向我解释为什么会发生这种情况以及如何防止这种情况发生?

1 个答案:

答案 0 :(得分:2)

这种行为方式是由于制作下采样时段而发生的。 间隔中的工作日数小于日历日。 这就是为什么星期五和星期一加入星期六和星期日,并作为一个单位表示。 星期六和星期日的值用于使用'how'和'closed'参数进行下采样。<​​/ p>

dates = ['1953-02-28', '1953-03-31', '1953-04-30', '1953-05-31']
values = [1,2,3,4]
monthly_ts  = pd.Series(values, index = pd.to_datetime(dates))

首次上传到日历日

calendar_daily_ts = monthly_ts.resample(rule='D').ffill()

让我们看看最后三个记录

In[8]: calendar_daily_ts[-3:]
Out[8]: 
1953-05-29    3
1953-05-30    3
1953-05-31    4
Freq: D, dtype: int64

如果我们使用mean和closed ='left'下采样到工作日,那么最后一个值将是3.33333

In [15]: calendar_daily_ts.resample(rule='B', closed='left').mean()[-2:]
Out[15]: 
1953-05-28    3.000000
1953-05-29    3.333333
Freq: B, dtype: float64

周五(1953-05-29)的价值计算为周五,周六和周日(3 + 3 + 4)/ 3的平均值

如果我们使用mean和closed ='right'下采样到工作日,则最后一个值将为3.5

In [16]: calendar_daily_ts.resample(rule='B', closed='right').mean()[-2:]
Out[16]: 
1953-05-28    3.0
1953-05-29    3.5
Freq: B, dtype: float64

周五(1953-05-29)的价值计算为周六,周日和下周一(3 + 4 + 0)/ 2的平均值

没有周五价值。

所以你问题中的观察结果是因为在1953-02-28(星期六),下采样的时期包括1953-02-27,1953-02-28,1953-03-01和1953-03-02。 默认间隔是左边的 - (1953-02-27,1953-02-28,1953-03-01)。 你得到了第一个 - 它是1953-02-27

另一个有趣的例子

In [45]: calendar_daily_ts[:4]
Out[45]: 
1953-02-27    1
1953-02-28    2
1953-03-01    3
1953-03-02    4
dtype: int64

In [47]: calendar_daily_ts.resample(rule='B', closed='left').first()[:4]
Out[47]: 
1953-02-27    1
1953-03-02    4
1953-03-03    1
1953-03-04    1
Freq: B, dtype: int64

In [48]: calendar_daily_ts.resample(rule='B', closed='right').first()[:4]
Out[48]: 
1953-02-26    1
1953-02-27    2
1953-03-02    1
1953-03-03    1
Freq: B, dtype: int64

看到差异! (1953-02-26,价值1)