本文通过一个分数统计分析的案例,串联介绍了 Pandas 的十个高级操作,帮助初学者快速掌握 Pandas 的一些常用技巧。
import pandas as pd
pd.__version__
多表合并
一次考试测验后,语文老师和数学老师分别批改完答卷,并统计了所有考生的得分。作为班主任,需要将所有学生的语文、数学两科成绩进行汇总。
df1 = pd.DataFrame({"Name": ["张三", "李四", "王五"], "Chinese": [36, 60, 81]})
df2 = pd.DataFrame({"Name": ["李四", "王五", "赵六"], "Math": [49, 64, 90]})
pd.merge(df1, df2, on="Name", how="inner")
内连接 (INNER JOIN
) 是一种多表合并方式,它只保留键的交集。在这个场景中,我们需要键的并集,那些缺失的分数表示缺考,此时可以使用外连接 (OUTER JOIN
)。
df = pd.merge(df1, df2, on="Name", how="outer")
df
此外,多表合并还有一种方式 concat
,它简单地将行和列拼接在一起。当多张表有相同列名时,合并后保留成一列;不同列名时,合并后保留所有列。
pd.concat([df1, df2])
处理缺失值
缺失的分数表示学生缺考,因此默认记为零分。
dfa = df.fillna(0)
dfa
索引列
通过 set_index
方法设置索引列,通过 reset_index
方法重置索引列。
dfi = dfa.set_index("Name")
dfi
dfi.reset_index()
对整个 DataFrame 应用函数
由于这次考生的成绩不理想,需要对分数进行“美化”。具体操作为:先对分数开平方根,再乘以 10,最后取整数部分。
dff = dfi.applymap(lambda x: round(10 * x**0.5))
dff
查询
各科成绩都在 80 分及以上的同学可以被评为优秀学生,请查询出这些学生。
dff.query("Chinese>=80 and Math>=80")
宽表转长表
当前的成绩表使用不同列来表示不同学科的成绩,如果未来需要增加英语、物理、化学、生物、政治、历史、地理等科目,就需要不断扩充列,导致表格变得非常宽。为了满足支持更多科目成绩的需求,另一种数据存储方式是使用长表,其中一列记录学科名称,另一列记录学生在该学科的分数。为了将现有的宽表转换为长表,可以采用以下方法。
dfl = pd.melt(
dff.reset_index(),
id_vars=["Name"],
value_vars=["Chinese", "Math"],
var_name="Subject",
value_name="Score",
)
dfl
数据透视表
透视一下班级里学生各科的成绩。
dfl.pivot_table(index="Name", columns="Subject", values="Score", aggfunc="sum")
分组聚合
统计班级里每位学生的各科成绩总分。
dfl.groupby("Name").sum("Score")
聚合函数还支持在每组数据中应用一个函数,例如计算每位学生的各科成绩的极差,以了解每位学生的偏科情况。
dfl.groupby("Name")["Score"].apply(lambda x: x.max() - x.min())
分桶操作
对连续值进行分桶操作,将其转换为离散值,是一种常用的数据处理方法。例如,我们希望将连续的分数值 Score 划分为不及格、及格、优秀三个等级,通过 60 分和 80 分作为分界点进行分桶。
dfl["Category"] = pd.cut(
dfl["Score"], bins=[0, 60, 80, 100], labels=["不及格", "及格", "优秀"], right=False
)
dfl
交叉分析
分析每位学生不及格、及格、优秀三档的分布情况,可以清楚看到王五有两门科目都是优秀。
pd.crosstab(dfl["Name"], dfl["Category"])