将Pandas长格式DataFrame转宽格式 生成Top列及优化性能
解决方案:高效实现Pandas长转宽并添加班级Top列
一、核心优化思路
针对30万行数据,pivot_table速度慢的根源是它默认会执行聚合逻辑(如均值、求和),而如果你的数据中(Class_ID, Class_size, Student_Number)是唯一组合,直接用无聚合的重塑方法(pivot或set_index+unstack)能大幅提升处理效率。
二、分步实现
假设原DataFrame包含列:Class_ID, Class_size, Student_Number, Score(存储学生考试分数)。
1. 预计算班级Top学号
先按班级分组,提取每个班级最高分对应的学号:
- 情况1:仅取第一个最高分学生
# 找到每个班级最高分的行索引,映射到对应学号 top_students = df.groupby(['Class_ID', 'Class_size'])['Score'].idxmax().map(df['Student_Number']) # 转为可合并的DataFrame top_students = top_students.reset_index(name='Top')
- 情况2:保留所有并列最高分的学生(用逗号分隔)
def collect_top_students(group): max_score = group['Score'].max() # 筛选所有最高分学生,转为字符串拼接 return ','.join(group[group['Score'] == max_score]['Student_Number'].astype(str)) top_students = df.groupby(['Class_ID', 'Class_size']).apply(collect_top_students).reset_index(name='Top')
2. 高效长转宽
用pivot直接重塑,避免不必要的聚合:
# 生成以班级为索引、学生学号为列的宽表 wide_df = df.pivot( index=['Class_ID', 'Class_size'], columns='Student_Number', values='Score' ) # 合并Top列到宽表 wide_df = wide_df.merge(top_students, on=['Class_ID', 'Class_size'], how='left') # 可选:移除列索引名称,让表格更整洁 wide_df.columns.name = None
替代写法:用set_index+unstack
效果和pivot一致,速度接近:
wide_df = df.set_index(['Class_ID', 'Class_size', 'Student_Number'])['Score'].unstack('Student_Number')
三、额外性能优化建议
- 优化数据类型:将
Class_ID转为category类型,减少内存占用,加快分组和重塑速度:df['Class_ID'] = df['Class_ID'].astype('category') - 处理缺失值:如果学生有缺考情况,宽表会产生
NaN,可按需填充:wide_df = wide_df.fillna(0) # 用0填充缺考分数 - 提前去重:如果数据存在重复的
(Class_ID, Class_size, Student_Number)组合,先去重再处理:df = df.drop_duplicates(subset=['Class_ID', 'Class_size', 'Student_Number'])
内容的提问来源于stack exchange,提问作者Ishigami
相关产品推荐
相关产品推荐

