【问题标题】:Pandas: use groupby to count difference between datesPandas:使用 groupby 计算日期之间的差异
【发布时间】:2016-08-12 10:00:10
【问题描述】:

我有 df:

i,Unnamed,ID,url,used_at,active_seconds,domain,subdomain,search_engine,search_term,diff_time,period
0,322015,0120bc30e78ba5582617a9f3d6dfd8ca,vk.com/antoninaribina,2015-12-31 09:16:05,35,vk.com,vk.com,None,None,,1
1,838267,0120bc30e78ba5582617a9f3d6dfd8ca,vk.com/feed,2015-12-31 09:16:38,54,vk.com,vk.com,None,None,33.0,1
2,838271,0120bc30e78ba5582617a9f3d6dfd8ca,vk.com/feed?section=photos,2015-12-31 09:17:32,34,vk.com,vk.com,None,None,54.0,1
3,322026,0120bc30e78ba5582617a9f3d6dfd8ca,vk.com/feed?section=photos&z=photo143297356_397216312%2Ffeed1_143297356_1451504298,2015-12-31 09:18:06,4,vk.com,vk.com,None,None,34.0,1
4,838275,0120bc30e78ba5582617a9f3d6dfd8ca,vk.com/feed?section=photos,2015-12-31 09:18:10,4,vk.com,vk.com,None,None,4.0,1
5,322028,7602962fb83ac2e2a0cb44158ca88464,vk.com/feed?section=comments,2015-12-29 09:18:14,8,vk.com,vk.com,None,None,4.0,1
6,322029,7602962fb83ac2e2a0cb44158ca88464,megarand.ru/contest/121070,2015-12-30 09:18:22,16,megarand.ru,megarand.ru,None,None,8.0,1
7,1870917,7602962fb83ac2e2a0cb44158ca88464,vk.com/feed?section=comments,2015-12-31 09:18:38,6,vk.com,vk.com,None,None,16.0,1

我需要在每个ID 打印第一个和最后一个日期之间的差异。我该怎么做? 我尝试使用df.groupby('ID')['used_at'].diff().dt.seconds,但它打印每 2 个字符串之间的差异

【问题讨论】:

    标签: python pandas dataframe group-by timedelta


    【解决方案1】:

    我认为您需要 groupbyfirstlast 不同:

    g = df.groupby('ID')['used_at']
    print (g.first() - g.last())
    ID
    0120bc30e78ba5582617a9f3d6dfd8ca   -1 days +23:57:55
    7602962fb83ac2e2a0cb44158ca88464   -3 days +23:59:36
    Name: used_at, dtype: timedelta64[ns]
    

    或申请iloc

    print (df.groupby('ID')['used_at'].apply(lambda g: g.iloc[0] - g.iloc[-1]))
    ID
    0120bc30e78ba5582617a9f3d6dfd8ca   -1 days +23:57:55
    7602962fb83ac2e2a0cb44158ca88464   -3 days +23:59:36
    Name: used_at, dtype: timedelta64[ns]
    

    timedelta 转换为seconds

    g = df.groupby('ID')['used_at']
    print ((g.first() - g.last()).dt.seconds)
    ID
    0120bc30e78ba5582617a9f3d6dfd8ca    86275
    7602962fb83ac2e2a0cb44158ca88464    86376
    Name: used_at, dtype: int64
    
    print (df.groupby('ID')['used_at'].apply(lambda g: g.iloc[0] - g.iloc[-1]).dt.seconds)
    ID
    0120bc30e78ba5582617a9f3d6dfd8ca    86275
    7602962fb83ac2e2a0cb44158ca88464    86376
    Name: used_at, dtype: int64
    

    感谢juanpa.arrivillagacomment

    如果日期时间已排序,您可以使用:

    df.groupby('ID').used_at.min() - df.groupby('ID').used_at.max()
    

    时间安排

    In [216]: %timeit (a(df))
    The slowest run took 4.30 times longer than the fastest. This could mean that an intermediate result is being cached.
    1000 loops, best of 3: 1.78 ms per loop
    
    In [217]: %timeit (b(df))
    1000 loops, best of 3: 1.8 ms per loop
    
    In [218]: %timeit (df.groupby('ID')['used_at'].apply(lambda g: g.iloc[0] - g.iloc[-1]).dt.seconds)
    1000 loops, best of 3: 1.53 ms per loop
    
    In [219]: %timeit (df.groupby('ID').agg(['first','last']).apply( lambda r: r['used_at','first'] - r['used_at','last'], axis=1).dt.seconds)
    100 loops, best of 3: 14.4 ms per loop
    

    计时代码:

    df = pd.concat([df]*1000).reset_index(drop=True)
    
    def a(df):
        g = df.groupby('ID')['used_at']
        return ((g.first() - g.last()).dt.seconds)
    
    def b(df):
        g = df.groupby('ID')['used_at']
        return ((g.min() - g.max()).dt.seconds)
    

    【讨论】:

    • 难题,因为我没有buy 列,所以我无法测试它。但是您的命令似乎返回了一些新的DataFrame,而不是系列,因此您可以使用df1 = df.groupby(['ID', ...。但是如果需要附加不同的输出,我猜你需要合并。最好在代码中添加df2,DataFrame 加上buy,这样会更清晰。
    • 如果删除 .apply(lambda x: x['date'] if x['buy']==1 else x['count_sec'],axis=1) 还是错误?
    • 嗯,我看到了问题。您不能以这种方式添加新数据。您需要先创建新的 DataFrame,例如 rep1= df.groupby('ID').agg(['first','last']).apply( lambda r: r['used_at','last'] - r['used_at','first'], axis=1).reset_index(),然后将其合并或连接到另一个 DataFrame,例如 pd.merge(df, rep1, on=['come_columns'])
    • 尝试添加.reset_index(name='new_name'),如果不行,需要.rename(columns={0:'new_name'})
    • 我认为它返回错误数据,因为它切断了日子。尝试print (g.last() - g.first()),然后是print ((g.last() - g.first()).dt.seconds)print (df.groupby('ID')['used_at'].apply(lambda g: g.iloc[-1] - g.iloc[0]).dt.seconds.reset_index()),其中swap last 和first。
    【解决方案2】:

    有一条线。

    df.groupby('ID').agg(['first','last']).apply( lambda r: r['used_at','last'] - r['used_at','first'], axis=1)
    

    第一个按列分组ID,然后为每个组取第一个和最后一个元素并计算差值last - first

    【讨论】:

    • 如何将其添加到现有表中?我尝试rep['days_to_buy'] = df.groupby('ID').agg(['first','last']).apply( lambda r: r['used_at','last'] - r['used_at','first'], axis=1).reset_index() ,但它返回ValueError: Wrong number of items passed 2, placement implies 1
    猜你喜欢
    • 2015-08-23
    • 2021-02-18
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多