Pandas 的十个高级操作

本文通过一个分数统计分析的案例,串联介绍了 Pandas 的十个高级操作,帮助初学者快速掌握 Pandas 的一些常用技巧。

In [1]:
import pandas as pd
In [2]:
pd.__version__
Out[2]:
'1.5.3'

多表合并

一次考试测验后,语文老师和数学老师分别批改完答卷,并统计了所有考生的得分。作为班主任,需要将所有学生的语文、数学两科成绩进行汇总。

In [3]:
df1 = pd.DataFrame({"Name": ["张三", "李四", "王五"], "Chinese": [36, 60, 81]})
In [4]:
df2 = pd.DataFrame({"Name": ["李四", "王五", "赵六"], "Math": [49, 64, 90]})
In [5]:
pd.merge(df1, df2, on="Name", how="inner")
Out[5]:
Name Chinese Math
0 李四 60 49
1 王五 81 64

内连接 (INNER JOIN) 是一种多表合并方式,它只保留键的交集。在这个场景中,我们需要键的并集,那些缺失的分数表示缺考,此时可以使用外连接 (OUTER JOIN)。

In [6]:
df = pd.merge(df1, df2, on="Name", how="outer")
df
Out[6]:
Name Chinese Math
0 张三 36.0 NaN
1 李四 60.0 49.0
2 王五 81.0 64.0
3 赵六 NaN 90.0

此外,多表合并还有一种方式 concat,它简单地将行和列拼接在一起。当多张表有相同列名时,合并后保留成一列;不同列名时,合并后保留所有列。

In [7]:
pd.concat([df1, df2])
Out[7]:
Name Chinese Math
0 张三 36.0 NaN
1 李四 60.0 NaN
2 王五 81.0 NaN
0 李四 NaN 49.0
1 王五 NaN 64.0
2 赵六 NaN 90.0

处理缺失值

缺失的分数表示学生缺考,因此默认记为零分。

In [8]:
dfa = df.fillna(0)
dfa
Out[8]:
Name Chinese Math
0 张三 36.0 0.0
1 李四 60.0 49.0
2 王五 81.0 64.0
3 赵六 0.0 90.0

索引列

通过 set_index 方法设置索引列,通过 reset_index 方法重置索引列。

In [9]:
dfi = dfa.set_index("Name")
dfi
Out[9]:
Chinese Math
Name
张三 36.0 0.0
李四 60.0 49.0
王五 81.0 64.0
赵六 0.0 90.0
In [10]:
dfi.reset_index()
Out[10]:
Name Chinese Math
0 张三 36.0 0.0
1 李四 60.0 49.0
2 王五 81.0 64.0
3 赵六 0.0 90.0

对整个 DataFrame 应用函数

由于这次考生的成绩不理想,需要对分数进行“美化”。具体操作为:先对分数开平方根,再乘以 10,最后取整数部分。

In [11]:
dff = dfi.applymap(lambda x: round(10 * x**0.5))
dff
Out[11]:
Chinese Math
Name
张三 60 0
李四 77 70
王五 90 80
赵六 0 95

查询

各科成绩都在 80 分及以上的同学可以被评为优秀学生,请查询出这些学生。

In [12]:
dff.query("Chinese>=80 and Math>=80")
Out[12]:
Chinese Math
Name
王五 90 80

宽表转长表

当前的成绩表使用不同列来表示不同学科的成绩,如果未来需要增加英语、物理、化学、生物、政治、历史、地理等科目,就需要不断扩充列,导致表格变得非常宽。为了满足支持更多科目成绩的需求,另一种数据存储方式是使用长表,其中一列记录学科名称,另一列记录学生在该学科的分数。为了将现有的宽表转换为长表,可以采用以下方法。

In [13]:
dfl = pd.melt(
    dff.reset_index(),
    id_vars=["Name"],
    value_vars=["Chinese", "Math"],
    var_name="Subject",
    value_name="Score",
)
dfl
Out[13]:
Name Subject Score
0 张三 Chinese 60
1 李四 Chinese 77
2 王五 Chinese 90
3 赵六 Chinese 0
4 张三 Math 0
5 李四 Math 70
6 王五 Math 80
7 赵六 Math 95

数据透视表

透视一下班级里学生各科的成绩。

In [14]:
dfl.pivot_table(index="Name", columns="Subject", values="Score", aggfunc="sum")
Out[14]:
Subject Chinese Math
Name
张三 60 0
李四 77 70
王五 90 80
赵六 0 95

分组聚合

统计班级里每位学生的各科成绩总分。

In [15]:
dfl.groupby("Name").sum("Score")
Out[15]:
Score
Name
张三 60
李四 147
王五 170
赵六 95

聚合函数还支持在每组数据中应用一个函数,例如计算每位学生的各科成绩的极差,以了解每位学生的偏科情况。

In [16]:
dfl.groupby("Name")["Score"].apply(lambda x: x.max() - x.min())
Out[16]:
Name
张三    60
李四     7
王五    10
赵六    95
Name: Score, dtype: int64

分桶操作

对连续值进行分桶操作,将其转换为离散值,是一种常用的数据处理方法。例如,我们希望将连续的分数值 Score 划分为不及格、及格、优秀三个等级,通过 60 分和 80 分作为分界点进行分桶。

In [17]:
dfl["Category"] = pd.cut(
    dfl["Score"], bins=[0, 60, 80, 100], labels=["不及格", "及格", "优秀"], right=False
)
dfl
Out[17]:
Name Subject Score Category
0 张三 Chinese 60 及格
1 李四 Chinese 77 及格
2 王五 Chinese 90 优秀
3 赵六 Chinese 0 不及格
4 张三 Math 0 不及格
5 李四 Math 70 及格
6 王五 Math 80 优秀
7 赵六 Math 95 优秀

交叉分析

分析每位学生不及格、及格、优秀三档的分布情况,可以清楚看到王五有两门科目都是优秀。

In [18]:
pd.crosstab(dfl["Name"], dfl["Category"])
Out[18]:
Category 不及格 及格 优秀
Name
张三 1 1 0
李四 0 2 0
王五 0 0 2
赵六 1 0 1

相关推荐