Python Pandas添加带有自定义工作日(CDay; CustomBusinessDay)的日期偏移列

时间:2018-10-16 03:13:17

标签: python pandas numpy

我想在日期列中添加自定义营业日偏移列:

>> import pandas as pd
>> from pandas.tseries.offsets import CustomBusinessDay

>> df = pd.DataFrame({'ship_date_et': ['2018-10-01' for x in range(10)], 'offset': [x for x in range(10)]})

>> df['offset'] = pd.to_timedelta(df['offset'], unit='D')

>> df['ship_date_et'] = pd.to_datetime(df['ship_date_et'])

>> df.dtypes
offset          timedelta64[ns]
ship_date_et     datetime64[ns]

>> df
    offset ship_date_et
0   0 days  2018-10-01
1   1 days  2018-10-01
2   2 days  2018-10-01
3   3 days  2018-10-01
4   4 days  2018-10-01
5   5 days  2018-10-01
6   6 days  2018-10-01
7   7 days  2018-10-01
8   8 days  2018-10-01
9   9 days  2018-10-01

>> holidays = ['2018-10-10'] # '2018-10-10' just a made-up holiday

>> cdays = CustomBusinessDay(holidays=holidays, weekmask='Mon Tue Wed Thu Fri') 

>> df['ship_date_et'] + df['offset'].apply(cdays)
0   2018-10-02
1   2018-10-03
2   2018-10-04
3   2018-10-05
4   2018-10-06
5   2018-10-07
6   2018-10-08
7   2018-10-09
8   2018-10-10
9   2018-10-11
dtype: datetime64[ns]

哪个是疯狂的错误。未计算周末(2018-10-06和2018-10-07)(Pandas文档说CDay包含了Weekends)。我只定义了2 weekmask天(星期一和星期二),这是不正确的。

我真的感到困惑和沮丧,因为这适用于普通的BDay

>> df['ship_date_et'] + df['offset'].dt.days.apply(BDay) # Doing dt.days to get integer for BDay since we defined df['offset'] as a `timedelta`
0   2018-10-01
1   2018-10-02
2   2018-10-03
3   2018-10-04
4   2018-10-05
5   2018-10-08
6   2018-10-09
7   2018-10-10
8   2018-10-11
9   2018-10-12

我想要的结果:

>> df['ship_date_et'] + df['offset'].apply(cdays)
0   2018-10-01
1   2018-10-02
2   2018-10-03
3   2018-10-04
4   2018-10-05
5   2018-10-08
6   2018-10-09
7   2018-10-11
8   2018-10-12
9   2018-10-15

我已经阅读了所有文档(包括numpy busday和Pandas)并仔细浏览了互联网,例如herehere),但是找不到发生这种情况的原因。最相关的部分是我在cdays的{​​{1}}定义是index=0,但是结果返回了我的0 days天+1。

当然,使用ship_date_et和以下内容也存在问题:

apply

熊猫给。

我将不胜感激任何反馈或输入。谢谢!

2 个答案:

答案 0 :(得分:0)

您似乎只将cdays应用于偏移量,而不是ship_date + offset。

(df['ship_date_et'] + df['offset']).apply(cdays)

答案 1 :(得分:0)

@dlstadther,虽然您的回答确实给了我日期偏移,但它并没有将周末或假日视为零。我认为这与我将df['offset']作为type timedelta的实现有关。结果是:

>> (df['ship_date_et'] + df['offset']).apply(cdays)
0   2018-10-02
1   2018-10-03
2   2018-10-04
3   2018-10-05
4   2018-10-08
5   2018-10-08
6   2018-10-08
7   2018-10-09
8   2018-10-11
9   2018-10-11
dtype: datetime64[ns]

并没有将周末和节假日视为零,不存在,无论您想怎么想,都没有继续关注计数器。我说这是由于我无法提出一个很好的问题。

我的回答:

一点点睡眠和烦恼:

>> df['new'] = df['ship_date_et'] + df['offset'].dt.days*cdays

这就是我想要的。

>> df
offset ship_date_et        new
0 0 days   2018-10-01 2018-10-01
1 1 days   2018-10-01 2018-10-02
2 2 days   2018-10-01 2018-10-03
3 3 days   2018-10-01 2018-10-04
4 4 days   2018-10-01 2018-10-05
5 5 days   2018-10-01 2018-10-08
6 6 days   2018-10-01 2018-10-09
7 7 days   2018-10-01 2018-10-11
8 8 days   2018-10-01 2018-10-12
9 9 days   2018-10-01 2018-10-15

在此示例中,“假期”和周末被跳过,并且计数器像BDay一样经过它们。

如果df['offset']的类型为int,则不必执行.dt.days