如何将多关联学生成绩记录透视转换为单条记录?求快捷方法
当然有更简洁高效的办法啦!完全不用写冗长的循环,Pandas自带的透视表相关函数就能轻松搞定你的需求,还能自动处理那些学生没选修课程的缺失数据。下面给你两种常用的方案,根据你的数据情况选就行:
1. 用pivot函数(适合无重复记录的场景)
如果你的数据里每个学生+科目只有一条记录(就像你给出的示例数据这样),pivot是最直接的选择:
首先先把你的示例数据再贴一下方便参考:
import pandas as pd df = pd.DataFrame([('Adel', "Subj1", 3.50 ,2.57), ('Adel', "Subj2", 2.75 ,3.6 ), ('Alexa',"Subj1", 1.75 ,3.25), ('Alexa',"Subj3", 3.15 ,2.25) ], columns=('Name', "Subj","Med", "Ach" ))
然后执行透视操作:
# 按Name分组,Subj作为列,Med和Ach作为值 pivoted_df = df.pivot(index='Name', columns='Subj', values=['Med', 'Ach'])
这时候你会得到一个带分层列的DataFrame,外层是Med、Ach,内层是科目名称。如果觉得分层列看着麻烦,可以把列名扁平化,让它更直观:
# 合并分层列名 pivoted_df.columns = ['_'.join(col) for col in pivoted_df.columns] # 把Name从索引变回普通列 pivoted_df.reset_index(inplace=True)
最终的结果会是这样的(缺失的科目自动填充NaN):
| Name | Med_Subj1 | Med_Subj2 | Med_Subj3 | Ach_Subj1 | Ach_Subj2 | Ach_Subj3 |
|---|---|---|---|---|---|---|
| Adel | 3.50 | 2.75 | NaN | 2.57 | 3.60 | NaN |
| Alexa | 1.75 | NaN | 3.15 | 3.25 | NaN | 2.25 |
2. 用pivot_table函数(适合有重复记录的场景)
如果你的数据里可能存在同一个学生+科目有多条记录(比如同一个科目多次考试的成绩),pivot_table会更灵活,它支持聚合操作(比如取均值、求和、取第一条等),同样会自动处理缺失值:
# 用first聚合,保留每个学生+科目的第一条记录;如果有重复值可以换成'mean'取平均 pivot_table_df = df.pivot_table(index='Name', columns='Subj', values=['Med', 'Ach'], aggfunc='first') # 同样可以扁平化列名 pivot_table_df.columns = ['_'.join(col) for col in pivot_table_df.columns] pivot_table_df.reset_index(inplace=True)
为什么这两种方法比循环好?
Pandas的这些内置函数都是矢量化操作,比手动写循环快得多,尤其是数据量大的时候差距会非常明显。而且它们会自动处理缺失数据,不用你自己写判断逻辑去填充空值,代码也更简洁易读。
内容的提问来源于stack exchange,提问作者SAM.Am
相关产品推荐
相关产品推荐

