如何用Pandas实现复杂分组:按ID统计并计算总耗时
解决Pandas按ID分组统计次数与总时长的问题
嘿,我来帮你搞定这个需求!要实现按ID分组统计出现次数,以及最早开单日期和最晚关单日期的天数差,我们需要分两步走:先处理日期格式,再做分组聚合。下面是完整的实现方案:
步骤1:准备数据并转换日期格式
首先把你的原始数据转换成DataFrame,同时必须把Date_Open和Date_Closed这两列从字符串转成datetime类型——不然直接计算日期差会出问题,因为字符串的排序逻辑和日期不一样。
代码如下:
import pandas as pd # 你的原始数据 data = { 'ID': [1, 1, 2, 2, 3], 'Date_Open': ['01/01/2019', '07/01/2019', '10/01/2019', '13/01/2019', '10/01/2019'], 'Date_Closed': ['02/01/2019', '09/01/2019', '11/01/2019', '19/01/2019', '11/01/2019'] } df = pd.DataFrame(data) # 转换日期格式,这里你的日期是DD/MM/YYYY格式,所以要指定format参数 df['Date_Open'] = pd.to_datetime(df['Date_Open'], format='%d/%m/%Y') df['Date_Closed'] = pd.to_datetime(df['Date_Closed'], format='%d/%m/%Y')
步骤2:分组聚合计算目标指标
接下来用groupby('ID')对数据分组,然后通过agg()方法一次性定义两个聚合规则:
Count_of_ID:用size()统计每个ID的出现次数(和count()效果差不多,这里用size更合适,因为它会统计所有行,包括空值,不过你的数据里没有空值)Total_Time_In_Days:先取每个ID的最早Date_Open和最晚Date_Closed,然后计算两者的天数差
我给你两种写法,选哪种都可以:
写法一:紧凑版
result = df.groupby('ID').agg( Count_of_ID=('ID', 'size'), Total_Time_In_Days=lambda x: (x.max() - df.loc[x.index, 'Date_Open'].min()).days ).reset_index()
写法二:更直观的分步版
这种写法会先计算中间的日期列,方便你检查数据是否正确,最后再删掉不需要的列:
# 先分组计算三个指标:次数、最早开单日期、最晚关单日期 temp = df.groupby('ID').agg( Count_of_ID=('ID', 'size'), earliest_open=('Date_Open', 'min'), latest_closed=('Date_Closed', 'max') ) # 计算天数差,然后整理成最终结果 result = temp.assign( Total_Time_In_Days=lambda x: (x['latest_closed'] - x['earliest_open']).dt.days ).drop(columns=['earliest_open', 'latest_closed']).reset_index()
最终结果
运行上面的代码后,result就是你想要的输出:
ID Count_of_ID Total_Time_In_Days 0 1 2 8 1 2 2 9 2 3 1 1
小提示
- 日期格式转换是关键!如果不转成datetime类型,
min()和max()会按字符串的字典序排序,结果肯定不对 - 如果你不确定日期格式,可以用
pd.to_datetime的dayfirst=True参数,不过指定format会更稳妥,避免歧义
内容的提问来源于stack exchange,提问作者Django0602
相关产品推荐
相关产品推荐

