如何基于userid分组转换Pandas DataFrame:统计频次与提取最新日期
Pandas分组统计与数据重塑实现方案
步骤1:数据预处理(转换日期格式)
首先需要把date列转换成datetime类型,这样才能正确提取最新日期:
import pandas as pd # 构造原始数据 data = { 'userid': [1,1,1,1,1,1,2,2,3,3,3,3], 'concessions': [0,0,1,0,1,1,0,0,1,0,1,1], 'reason': ['aaa','aaa','bbb','ccc','aaa','ccc','aaa','aaa','bbb','ccc','aaa','ccc'], 'contact': ['call','chat','call','mail','call','call','call','chat','chat','mail','mail','call'], 'date': ['','','01-01-1990','','31-12-1992','15-06-1994','','','01-05-1990','','10-02-1991','21-08-1995'] } df = pd.DataFrame(data) # 转换date列为datetime,空值转为NaT df['date'] = pd.to_datetime(df['date'], format='%d-%m-%Y', errors='coerce')
步骤2:拆分统计任务并合并结果
我们可以把不同的统计项分开计算,再通过userid合并:
- 统计concessions总数与最新日期
# 分组计算concessions总和、最新日期 agg_basic = df.groupby('userid').agg( concessions=('concessions', 'sum'), date=('date', 'max') )
- 统计各reason类型的频次
用pd.get_dummies将reason列转为哑变量,再分组求和:
reason_counts = pd.get_dummies(df['reason']).groupby(df['userid']).sum()
- 统计各contact类型的频次
同理处理contact列:
contact_counts = pd.get_dummies(df['contact']).groupby(df['userid']).sum()
- 合并所有统计结果
用pd.concat把三个结果按userid合并,最后重置索引(让userid回到列中):
# 合并数据 final_df = pd.concat([agg_basic, reason_counts, contact_counts], axis=1).reset_index() # 将date列转回原格式(空值保留为空字符串) final_df['date'] = final_df['date'].dt.strftime('%d-%m-%Y').fillna('')
最终输出
运行上述代码后,final_df的结果与需求格式完全一致:
userid concessions aaa bbb ccc call chat mail date 0 1 3 3 1 2 4 1 1 15-06-1994 1 2 0 2 0 0 1 1 0 2 3 3 1 1 2 1 1 2 21-08-1995
补充说明
pd.get_dummies会自动识别reason/contact的所有类别并转为对应列,统计每个userid下的出现次数,比手动用value_counts更高效,且直接生成结构化DataFrame。- 转换日期时用
errors='coerce'把空字符串转为NaT(缺失时间值),后续取max时会自动忽略空值,正确获取最新日期。 - 如果原始数据
date列格式不同,需调整pd.to_datetime的format参数匹配格式。
内容的提问来源于stack exchange,提问作者Mariners
相关产品推荐
相关产品推荐

