如何计算数据框中分组行集合之前的差异

时间:2014-02-01 17:18:40

标签: python pandas

我正在寻找Pandas中同时分组/行上行差异问题的帮助。问题完全如R:How to calculate time difference between datetimes, for each group (student-contract)?

所述

我有这样的数据:

#   USER_ID CONTRACT_REF SUBMISSION_DATE  
1        1        A        20/6 01:00   
2        1        A        20/6 02:00   
3        1        B        20/6 03:00   
4        4        A        20/6 04:00   
5        5        A        20/6 05:00   
6        5        B        20/6 06:00   
7        7        A        20/6 07:00   
8        7        B        20/6 08:00   
9        7        B        20/6 09:30   
10       7        B        20/6 10:00   

我想为每个唯一的USER_ID - CONTRACT_REF对计算上次提交的时间差

注意:每个USER_ID - CONTRACT_REF对的第一次出现必须为零(或null)。

因此输出应如下所示:

#   USER_ID CONTRACT_REF SUBMISSION_DATE   TIME_DIFFERENCE
1        1        A        20/6 01:00             0
2        1        A        20/6 02:00             1
3        1        B        20/6 03:00             0
4        4        A        20/6 04:00             0
5        5        A        20/6 05:00             0          
6        5        B        20/6 06:00             0
7        7        A        20/6 07:00             0
8        7        A        20/6 08:00             1
9        7        A        20/6 09:30             1.5
10       7        B        20/6 10:00             0

我目前正在从R转移到Pandas,虽然我发现语法令人耳目一新,但在涉及数据帧的复杂功能时,我有点难过。

提前感谢任何提示!

1 个答案:

答案 0 :(得分:8)

[注意:您的数据似乎与您想要的输出不符;在第二个中没有CONTRACT_REF C,甚至在你的输出中,我不明白为什么5, B行是1而不是0.我假设这些都是你的错误。由于你没有评论,我将使用输出中的数据,因为它会导致更有趣的列。]

我可能会做类似

的事情
df["SUBMISSION_DATE"] = pd.to_datetime(df["SUBMISSION_DATE"],dayfirst=True)

gs = df.groupby(["USER_ID", "CONTRACT_REF"])["SUBMISSION_DATE"]
df["TIME_DIFF"] = gs.diff().fillna(0) / pd.datetools.timedelta(hours=1)

产生

>>> df
    #  USER_ID CONTRACT_REF     SUBMISSION_DATE  TIME_DIFF
0   1        1            A 2014-06-20 01:00:00        0.0
1   2        1            A 2014-06-20 02:00:00        1.0
2   3        1            B 2014-06-20 03:00:00        0.0
3   4        4            A 2014-06-20 04:00:00        0.0
4   5        5            A 2014-06-20 05:00:00        0.0
5   6        5            B 2014-06-20 06:00:00        0.0
6   7        7            A 2014-06-20 07:00:00        0.0
7   8        7            A 2014-06-20 08:00:00        1.0
8   9        7            A 2014-06-20 09:30:00        1.5
9  10        7            B 2014-06-20 10:00:00        0.0

[10 rows x 5 columns]

一些解释:从像

这样的数据框开始
>>> df
    #  USER_ID CONTRACT_REF SUBMISSION_DATE
0   1        1            A      20/6 01:00
1   2        1            A      20/6 02:00
2   3        1            B      20/6 03:00
3   4        4            A      20/6 04:00
4   5        5            A      20/6 05:00
5   6        5            B      20/6 06:00
6   7        7            A      20/6 07:00
7   8        7            A      20/6 08:00
8   9        7            A      20/6 09:30
9  10        7            B      20/6 10:00

[10 rows x 4 columns]

我们希望将SUBMISSION_DATE列从字符串转换为实际日期对象:

>>> df["SUBMISSION_DATE"] = pd.to_datetime(df["SUBMISSION_DATE"],dayfirst=True)
>>> df
    #  USER_ID CONTRACT_REF     SUBMISSION_DATE
0   1        1            A 2014-06-20 01:00:00
1   2        1            A 2014-06-20 02:00:00
2   3        1            B 2014-06-20 03:00:00
3   4        4            A 2014-06-20 04:00:00
4   5        5            A 2014-06-20 05:00:00
5   6        5            B 2014-06-20 06:00:00
6   7        7            A 2014-06-20 07:00:00
7   8        7            A 2014-06-20 08:00:00
8   9        7            A 2014-06-20 09:30:00
9  10        7            B 2014-06-20 10:00:00

[10 rows x 4 columns]

然后我们可以按USER_IDCONTRACT_REF进行分组,然后选择SUBMISSION_DATE列:

>>> gs = df.groupby(["USER_ID", "CONTRACT_REF"])["SUBMISSION_DATE"]
>>> gs
<pandas.core.groupby.SeriesGroupBy object at 0xa7af08c>

然后我们可以区分每组:

>>> gs.diff()
0        NaT
1   01:00:00
2        NaT
3        NaT
4        NaT
5        NaT
6        NaT
7   01:00:00
8   01:30:00
9        NaT
dtype: timedelta64[ns]

NaT,非常时,是NaN的时间等价物。我们可以填写0:

>>> gs.diff().fillna(0)
0   00:00:00
1   01:00:00
2   00:00:00
3   00:00:00
4   00:00:00
5   00:00:00
6   00:00:00
7   01:00:00
8   01:30:00
9   00:00:00
dtype: timedelta64[ns]

既然你想要用几小时来衡量事物,我们可以将时间分为1小时:

>>> gs.diff().fillna(0) / pd.datetools.timedelta(hours=1)
0    0.0
1    1.0
2    0.0
3    0.0
4    0.0
5    0.0
6    0.0
7    1.0
8    1.5
9    0.0
dtype: float64

将其分配给框架:

>>> df["TIME_DIFF"] = gs.diff().fillna(0) / pd.datetools.timedelta(hours=1)

我们已经完成了:

>>> df
    #  USER_ID CONTRACT_REF     SUBMISSION_DATE  TIME_DIFF
0   1        1            A 2014-06-20 01:00:00        0.0
1   2        1            A 2014-06-20 02:00:00        1.0
2   3        1            B 2014-06-20 03:00:00        0.0
3   4        4            A 2014-06-20 04:00:00        0.0
4   5        5            A 2014-06-20 05:00:00        0.0
5   6        5            B 2014-06-20 06:00:00        0.0
6   7        7            A 2014-06-20 07:00:00        0.0
7   8        7            A 2014-06-20 08:00:00        1.0
8   9        7            A 2014-06-20 09:30:00        1.5
9  10        7            B 2014-06-20 10:00:00        0.0

[10 rows x 5 columns]