You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas分组聚合结果中补充对应行数据

问题描述

我有如下结构的Pandas DataFrame:

import pandas as pd
df = pd.DataFrame([[1,'A','X','1/2/22 12:00:00AM','1/1/22 12:00:00 AM'],
[1,'A','X','1/1/22 1:00:00AM','1/1/22 12:00:00 AM'],
[1,'A','Y','1/3/22 12:00:00AM','1/2/22 12:00:00 AM'],
[1,'B','X','1/1/22 1:00:00AM','1/1/22 12:00:00 AM'],
[2,'A','X','1/2/22 12:00:00AM','1/1/22 12:00:00 AM'],
[2,'A','X','1/1/22 1:00:00AM','1/1/22 12:00:00 AM']],
columns = ['ID','Category','Site','Task Completed','Access Completed'])

对应的表格:

IDCategorySiteTask CompletedAccess Completed
1AX1/2/22 12:00:00AM1/1/22 12:00:00 AM
1AY1/3/22 12:00:00AM1/2/22 12:00:00 AM
1AX1/1/22 1:00:00AM1/1/22 12:00:00 AM
1BX1/1/22 1:00:00AM1/1/22 12:00:00 AM
2AX1/2/22 12:00:00AM1/1/22 12:00:00 AM
2AX1/1/22 1:00:00AM1/1/22 12:00:00 AM

注意:每个ID/Site/Category组合对应的Access Completed日期是一致的,不受实例数量影响。

我需要计算每个ID/Category/Site组合的Access Completed与首次Task Completed之间的时间差(小时),同时在结果中保留首次Task Completed日期和Access Completed日期。

现有代码如下:

df[['Task Completed','Access Completed']] = \
    df[['Task Completed','Access Completed']].apply(lambda x: pd.to_datetime(x))

res = df.sort_values('Task Completed').groupby(['ID','Category','Site']).first()
res = res['Task Completed'].sub(res['Access Completed'])\
    .dt.total_seconds().div(3600).reset_index(drop=False).rename(
        columns={0:'Time Difference'})

当前输出:

ID Category Site  Time Difference
0   1        A    X              1.0
1   1        A    Y             24.0
2   1        B    X              1.0
3   2        A    X              1.0

期望结果:

IDCategorySiteTime DifferenceFirst Task CompletedAccess Completed
1AX11/1/22 1:00:00AM1/1/22 12:00:00 AM
1AY241/3/22 12:00:00AM1/2/22 12:00:00 AM
1BX11/1/22 1:00:00AM1/1/22 12:00:00 AM
2AX11/1/22 1:00:00AM1/1/22 12:00:00 AM
解决方案

不需要丢弃分组后的其他列,直接在分组结果上计算时间差,同时保留需要的日期列即可:

import pandas as pd

# 转换时间列为datetime类型
df[['Task Completed','Access Completed']] = df[['Task Completed','Access Completed']].apply(pd.to_datetime)

# 按分组键聚合,保留首次任务完成时间和对应访问完成时间
grouped = df.sort_values('Task Completed').groupby(['ID','Category','Site']).agg(
    First_Task_Completed=('Task Completed', 'first'),
    Access_Completed=('Access Completed', 'first')
).reset_index()

# 计算小时级时间差
grouped['Time Difference'] = (grouped['First_Task_Completed'] - grouped['Access_Completed']).dt.total_seconds() / 3600

# 调整列顺序为期望格式
result = grouped[['ID', 'Category', 'Site', 'Time Difference', 'First_Task_Completed', 'Access_Completed']]

# 可选:将时间列格式化为原字符串样式
result['First_Task_Completed'] = result['First_Task_Completed'].dt.strftime('%m/%d/%y %I:%M:%S%p')
result['Access_Completed'] = result['Access_Completed'].dt.strftime('%m/%d/%y %I:%M:%S %p')

# 可选:将时间差转为整数
result['Time Difference'] = result['Time Difference'].astype(int)

print(result)

运行后输出:

ID Category Site  Time Difference First_Task_Completed Access_Completed
0   1        A    X                1      01/01/22 01:00:00AM  01/01/22 12:00:00 AM
1   1        A    Y               24      01/03/22 12:00:00AM  01/02/22 12:00:00 AM
2   1        B    X                1      01/01/22 01:00:00AM  01/01/22 12:00:00 AM
3   2        A    X                1      01/01/22 01:00:00AM  01/01/22 12:00:00 AM

说明

  1. 使用agg方法明确指定需要保留的列,避免丢失日期信息;
  2. 计算时间差时直接基于保留的日期列操作;
  3. 最后可根据需求格式化时间列的显示样式,以及调整时间差的类型;
  4. 因为每个分组的Access Completed日期一致,用first/max/min都能得到正确值。

内容的提问来源于stack exchange,提问作者CowboyCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 11:30:51