【问题标题】:Time difference within group by objects in Python PandasPython Pandas中按对象分组内的时间差
【发布时间】:2017-06-15 05:57:25
【问题描述】:

我有一个如下所示的数据框:

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

我无法弄清楚这一点!有没有办法解决这个问题? 任何帮助将不胜感激! 提前非常感谢您!

【问题讨论】:

  • Does this post help?这只是比较 DateTime 对象的一种简单方法。我对数据框不是很熟悉,但如果我没记错的话,你可以遍历某些列。

标签: python pandas difference data-science pandas-groupby


【解决方案1】:
df.assign(
    timediff=df.sort_values(
        'datetime', ascending=False
    ).groupby(['from', 'to']).datetime.diff(-1).dt.seconds.div(60).fillna(0))

【讨论】:

    【解决方案2】:

    我认为你需要:

    groupbyapply 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
    

    【讨论】:

    • 非常感谢!!这行得通,但我也希望“其他”列保持原样!
    • 好的,我添加解决方案。
    【解决方案3】:

    几乎和上面一样,但没有apply

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

    【讨论】:

    • 我发现在 jezrael 的回答中使用 .apply() 比直接调用 .diff() 稍微快一点(例如 1000 行的 %timeit,100 个循环,最好的 3:10.9ms/loop应用和 11.1 毫秒/循环不应用)
    • ``` .astype('timedelta64[m]').fillna(0) ``` 代替 ``` .dt.seconds.fillna(0) ``` 也很舒服
    猜你喜欢
    • 2021-03-06
    • 2021-04-24
    • 2013-01-16
    • 2018-02-12
    • 2016-11-27
    • 2018-10-07
    • 1970-01-01
    • 2018-09-04
    • 2017-01-30
    相关资源
    最近更新 更多