Pandas按组计算最大日期、日期间隔统计值及记录数方法
Pandas 分组计算日期指标优化实现
问题背景
现有如下结构的DataFrame:
sub_id,teacher,div,pid,pos_date 1,ABC,SCIENCE,A1,12/10/2021 1,ABC,SCIENCE,A1,22/06/2019 1,ABC,SCIENCE,A1,12/12/2018 1,ABC,SCIENCE,A1,27/11/2020 1,DEF,CHEMISTRY,A1,12/10/2021 1,DEF,CHEMISTRY,A2,11/11/2018 1,DEF,CHEMISTRY,A2,12/10/2021 1,ABC,SCIENCE,A2,12/10/2019 1,ABC,SCIENCE,A2,12/10/2020 1,ABC,SCIENCE,A3,12/11/2021 1,ABC,SCIENCE,A3,22/03/2022 1,ABC,SCIENCE,A4,22/10/2021 1,ABC,SCIENCE,A4,12/04/2021
对应读入代码:
df = pd.read_clipboard()
需要实现的逻辑:
- 按
sub_id、teacher、div、pid四个字段分组 - 每个分组计算4个指标:
- 分组内
pos_date的最大值 - 组内
pos_date日期间隔的平均值 - 组内
pos_date日期间隔的中位数 - 组内记录总条数
- 分组内
最初实现的代码存在重复分组、效率低、写法冗余的问题:
df.set_index(['sub_id','teacher','div','pid']).groupby(['sub_id','teacher','div','pid'])['pos_date'].max() df.set_index(['sub_id','teacher','div','pid']).groupby(['sub_id','teacher','div','pid'])['pos_date'].average() df.set_index(['sub_id','teacher','div','pid']).groupby(['sub_id','teacher','div','pid'])['pos_date'].median() df.set_index(['sub_id','teacher','div','pid']).groupby(['sub_id','teacher','div','pid'])['pos_date'].size()
期望输出格式参考:
优化实现方案
前置预处理
首先需要将pos_date字段转为标准日期类型,否则无法正确计算日期间隔,注意匹配原始数据的日/月/年格式:
import pandas as pd df['pos_date'] = pd.to_datetime(df['pos_date'], format='%d/%m/%Y')
单次分组聚合实现
只需要执行一次分组操作,通过自定义聚合函数一次性计算所有指标,避免重复遍历数据:
def calc_group_metrics(date_series: pd.Series) -> pd.Series: # 先对分组内日期升序排序 sorted_dates = date_series.sort_values() # 计算相邻日期的间隔,转为天为单位,去掉首行空值 day_intervals = sorted_dates.diff().dt.days.dropna() # 返回所有需要的指标 return pd.Series({ 'max_pos_date': sorted_dates.iloc[-1], 'avg_interval_days': day_intervals.mean().round(1), 'median_interval_days': day_intervals.median(), 'record_count': len(date_series) }) # 单次分组完成所有计算 result = df.groupby( ['sub_id', 'teacher', 'div', 'pid'], as_index=False )['pos_date'].apply(calc_group_metrics)
优化点说明
- 无需提前设置索引,直接传入分组字段即可,减少冗余操作
- 仅执行一次分组遍历,相比原写法四次重复分组,数据量越大性能优势越明显
- 计算间隔前先对日期排序,保证间隔计算逻辑准确
- 间隔直接转换为天数值,结果更易读,可根据业务需要保留timedelta格式
内容的提问来源于stack exchange,提问作者The Great
相关产品推荐
相关产品推荐

