Python如何对DataFrame多日期数据按年月分组统计各阶段流程数
解决方案
步骤1:宽表转长表
使用pd.melt把分散的20个阶段的状态、日期列整合成规范的长结构,避免循环遍历的冗余代码:
import pandas as pd # 提取所有阶段相关列 status_cols = [col for col in df.columns if 'Status' in col] completion_cols = [col for col in df.columns if 'Completion' in col] # 转换状态列到长表 df_status = df.melt( id_vars='id', value_vars=status_cols, var_name='stage', value_name='status' ) df_status['stage'] = df_status['stage'].str.replace(' Status', '', regex=False) # 转换完成日期列到长表 df_completion = df.melt( id_vars='id', value_vars=completion_cols, var_name='stage', value_name='completion_date' ) df_completion['stage'] = df_completion['stage'].str.replace(' Completion', '', regex=False) # 合并得到每个id+阶段的唯一明细行 df_long = pd.merge(df_status, df_completion, on=['id', 'stage'])
步骤2:日期格式化与统计维度提取
把日期转为标准格式,提取后续分组用的年月字段:
# 转datetime格式,无效日期自动转空值NaT df_long['completion_date'] = pd.to_datetime(df_long['completion_date'], errors='coerce') # 提取年月,格式为2021-01,作为统计维度 df_long['year_month'] = df_long['completion_date'].dt.to_period('M')
如果原始表的状态值为英文,可提前做映射统一为中文:
df_long['status'] = df_long['status'].replace({'Completed':'已完成', 'Open':'开放'})
步骤3:多维度分组统计
按年月、阶段、状态三个维度分组计数即可得到目标结果:
# 分组计数 result = df_long.groupby(['year_month', 'stage', 'status'], dropna=False)['id'].count().reset_index(name='count') # 如果需要转为年月为行、阶段+状态为列的宽表展示,可补充透视逻辑 result_pivot = result.pivot_table( index='year_month', columns=['stage', 'status'], values='count', fill_value=0 ).reset_index()
结果说明
- 已完成状态的统计会自动匹配非空完成日期对应的年月,空日期不会计入已完成统计
- 开放状态的统计直接匹配status字段即可,无需关联日期,空日期的条目会正常纳入计数
内容的提问来源于stack exchange,提问作者Peter Gould
相关产品推荐
相关产品推荐

