Python Pandas中分组对象的时间差异

18

我有一个数据框,看起来像这样:

from    to         datetime              other
-------------------------------------------------
11      1     2016-11-06 22:00:00          -
11      1     2016-11-06 20:00:00          -
11      1     2016-11-06 15:45:00          -
11      12    2016-11-06 15:00:00          -
11      1     2016-11-06 12:00:00          -
11      18    2016-11-05 10:00:00          -
11      12    2016-11-05 10:00:00          -
12      1     2016-10-05 10:00:59          -
12      3     2016-09-06 10:00:34          -

我想要按照"from"和"to"列来进行分组,然后按照"datetime"列进行降序排序,并最后计算这些被分组的对象中当前时间与下一个时间之间的时间差。例如,在这种情况下,我希望有一个如下所示的数据框:

from    to     timediff in minutes                                          others
11      1            120
11      1            255
11      1            225
11      1            0 (preferrably subtract this date from the epoch)
11      12           300
11      12           0
11      18           0
12      1            25
12      3            0

我无法理解如何解决这个问题!!是否有出路?非常感谢任何帮助!!非常感谢!


这篇帖子有帮助吗?它只是一个简单的比较 DateTime 对象的方法。我对数据框不是非常熟悉,但如果我没记错的话,你可以遍历特定列。 - Pike D.
3个回答

19
df.assign(
    timediff=df.sort_values(
        'datetime', ascending=False
    ).groupby(['from', 'to']).datetime.diff(-1).dt.seconds.div(60).fillna(0))

输入图像描述


17

我认为你需要:

groupby结合apply,使用sort_valuesdiff函数,将Timedelta转换为分钟,通过seconds函数向下取整除以60

使用fillnasort_index函数,删除索引中的第2级别

df = df.groupby(['from','to']).datetime
       .apply(lambda x: x.sort_values().diff().dt.seconds // 60)
       .fillna(0)
       .sort_index()
       .reset_index(level=2, drop=True)
       .reset_index(name='timediff in minutes')

print (df)

   from  to  timediff in minutes 
0    11   1                 120.0
1    11   1                 255.0
2    11   1                 225.0
3    11   1                   0.0
4    11  12                 300.0
5    11  12                   0.0
6    11  18                   0.0
7    12   3                   0.0
8    12   3                   0.0

df = df.join(df.groupby(['from','to'])
               .datetime
               .apply(lambda x: x.sort_values().diff().dt.seconds // 60)
               .fillna(0)
               .reset_index(level=[0,1], drop=True)
               .rename('timediff in minutes'))
print (df)
   from  to            datetime other  timediff in minutes
0    11   1 2016-11-06 22:00:00     -                120.0
1    11   1 2016-11-06 20:00:00     -                255.0
2    11   1 2016-11-06 15:45:00     -                225.0
3    11  12 2016-11-06 15:00:00     -                300.0
4    11   1 2016-11-06 12:00:00     -                  0.0
5    11  18 2016-11-05 10:00:00     -                  0.0
6    11  12 2016-11-05 10:00:00     -                  0.0
7    12   3 2016-10-05 10:00:59     -                  0.0
8    12   3 2016-09-06 10:00:34     -                  0.0

非常感谢!这个可以用,但我也希望“其他”列保持原样! - Gingerbread
好的,我为此添加解决方案。 - jezrael

14

与上面几乎相同,但没有 apply

result = df.sort_values(['from','to','datetime'])\
           .groupby(['from','to'])['datetime']\
           .diff().dt.seconds.fillna(0)

1
我发现使用像jezrael答案中的.apply()比直接调用.diff()略快一些(例如,在1000行,100个循环,3次中的最佳结果上进行%timeit,使用apply为10.9ms/loop,而不使用apply为11.1ms/loop)。 - Quetzalcoatl
.astype('timedelta64[m]').fillna(0) 这个方法也很方便,可以替代.dt.seconds.fillna(0) - Talis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接