与Pandas Groupby在两列日期之间的营业日

时间:2016-06-01 17:27:32

标签: python python-2.7 numpy pandas

我在Dataframe中有一个Pandas,其中包含一个字母和两个日期作为列。我想使用shift(1)计算上一行的两个日期列之间的差异,前提是Letter值相同(使用groupby)。复杂的部分是我想计算工作日,而不仅仅是经过的天数。我发现这样做的最好方法是使用numpy.busday_count,它将两个列表作为参数。我基本上试图使用.apply使每一行成为它自己的列表。不确定这是否是最好的方法,但遇到一些不明确的问题。

import pandas as pd
from datetime import datetime
import numpy as np

# create dataframe
df = pd.DataFrame(data=[['A', datetime(2016,01,07), datetime(2016,01,09)],
                        ['A', datetime(2016,03,01), datetime(2016,03,8)],
                        ['B', datetime(2016,05,01), datetime(2016,05,10)],
                        ['B', datetime(2016,06,05), datetime(2016,06,07)]],
                   columns=['Letter', 'First Day', 'Last Day'])

# convert to dates since pandas reads them in as time series
df['First Day'] = df['First Day'].apply(lambda x: x.to_datetime().date())
df['Last Day'] = df['Last Day'].apply(lambda x: x.to_datetime().date())

df['Gap'] = (df.groupby('Letter')
                         .apply(
                                lambda x: (
                                            np.busday_count(x['First Day'].shift(1).tolist(),
                                                            x['Last Day'].shift(1).tolist())))
                         .reset_index(drop=True))
print df

我在lambda函数上收到以下错误。我不确定它有什么问题,因为两个传递的参数应该是日期:

ValueError: Could not convert object to NumPy datetime

期望的输出:

  Letter   First Day    Last Day   Gap
0      A  2016-01-07  2016-01-09  NAN
1      A  2016-03-01  2016-03-08  1
2      B  2016-05-01  2016-05-10  NAN
3      B  2016-06-05  2016-06-07  7

1 个答案:

答案 0 :(得分:1)

以下情况应该有效 - 首先从日期数字中删除前导零:

df = pd.DataFrame(data=[['A', datetime(2016, 1, 7), datetime(2016, 1, 9)],
                        ['A', datetime(2016, 3, 1), datetime(2016, 3, 8)],
                        ['B', datetime(2016, 5, 1), datetime(2016, 5, 10)],
                        ['B', datetime(2016, 6, 5), datetime(2016, 6, 7)]],
                  columns=['Letter', 'First Day', 'Last Day'])

df['Gap'] = df.groupby('Letter')
              .apply(
               lambda x: 
                   pd.DataFrame(
                       np.busday_count(x['First Day'].tolist(), x['Last Day'].tolist())).shift())
                  .reset_index(drop=True)

  Letter  First Day   Last Day  Gap
0      A 2016-01-07 2016-01-09  NaN
1      A 2016-03-01 2016-03-08  2.0
2      B 2016-05-01 2016-05-10  NaN
3      B 2016-06-05 2016-06-07  6.0

我认为您不需要进行.date()转换。

相关问题