每个人都知道 Python 是一种高效、简洁、优雅的语言。然而 Python 也有很多坑,现在老宅开一个新系列,分享老宅在学习和实践中总结的经验和教训,不定期分享。
第一个经验就是要吐槽数据框的切片。Python 有很多第三方的模块(比如 pandas 这样的数据科学神器),对提升 Python 的实用性贡献很大。然而模块多就有一个副作用:语法的不一致性。老宅在学习 pandas 的过程中就被数据框切片的复杂语法搞得挠头。
本文参考了 http://chris.friedline.net/2015-12-15-rutgers/lessons/python2/02-index-slice-subset.html
,特此致谢。
数据框的切片,是在列表的切片的基础上发展起来的。不过列表是一维,数据框是二维,因此数据框切片有自己独特的方法。所以数据框的切片有两个风格:原生风格和 pandas 风格(这两个风格是老宅自己总结的…)。在总结以前,我们先构建数据集:
1 | import pandas as pd |
sepal_length | sepal_width | petal_length | petal_width | |
---|---|---|---|---|
aa | 5.1 | 3.5 | 1.4 | 0.2 |
ab | 4.9 | 3.0 | 1.4 | 0.2 |
ac | 4.7 | 3.2 | 1.3 | 0.2 |
ad | 4.6 | 3.1 | 1.5 | 0.2 |
ae | 5.0 | 3.6 | 1.4 | 0.2 |
原生风格
切片单列
df.column
方法
直接在数据框后面使用 .
连接列名。例如:
1 | 1:5] iris.sepal_length[ |
这个方法不需要用 ""
括上列,非常方便。不过这样有个潜在的局限:如果列名里有空格,这个方法就不好用了,就要用下面的方法。
df["column"]
方法
这个方法的好处是引号内可以有特殊符号,比如空格。这样切片稍微麻烦一点,但是还可以接受。
df[["column"]]
方法
这个方法与上面一样都用来切片单列。有什么不同呢?请看下面的例子:
1 | "sepal_length"][1:5] iris[ |
sepal_length | |
---|---|
ab | 4.9 |
ac | 4.7 |
ad | 4.6 |
ae | 5.0 |
单中括号和双中括号的区别在于单中括号返回的是序列,而双中括号返回的是数据框。
切片多列
df[["column1", "columns2"...]]
方法
因为多个列组合在一起是一个数据框,所以必须使用双中括号来切片。列名要用引号括起来。df[list]
方法
这里就体现出不一致性了:假如我们先将想要切片的列放入一个列表,就可以使用单中括号,而且不需要使用引号。1
2"sepal_length","petal_length"] lst = [
iris[lst].head()
sepal_length | petal_length | |
---|---|---|
aa | 5.1 | 1.4 |
ab | 4.9 | 1.4 |
ac | 4.7 | 1.3 |
ad | 4.6 | 1.5 |
ae | 5.0 | 1.4 |
切片行
使用索引切片
哪怕数据框的行已经有的自定义索引名,照样可以使用数字 0 - ~ 切片。1
1:5] iris[
sepal length sepal width petal length petal width ab 4.9 3.0 1.4 0.2 ac 4.7 3.2 1.3 0.2 ad 4.6 3.1 1.5 0.2 ae 5.0 3.6 1.4 0.2 使用行名切片
1
"ae":"ag"] iris[
sepal_length sepal_width petal_length petal_width ae 5.0 3.6 1.4 0.2 af 5.4 3.9 1.7 0.4 ag 4.6 3.4 1.4 0.3
行切片还有一个列切片不具备的功能:切片连续的行。如果数据框的行名和列名不一致,pandas 会自动判断你在切片行还是列。如果一致嘛…pandas 就不知所措了。这时候就要用到下面的 pandas 风格切片。
pandas 风格切片
df.loc[“indexes”, “columns”] 基于行、列的名称切片
注意行和列都是用的复数形式,意味着可以同时切片多行或多列。同时也可以切片范围内的行或列,使用 :
即可。
1 | "ae":"ag", ["sepal_length","petal_length"]] iris.loc[ |
sepal_length | petal_length | |
---|---|---|
ae | 5.0 | 1.4 |
af | 5.4 | 1.7 |
ag | 4.6 | 1.4 |
想切片全部的行或列,只需要单独使用 :
即可。
1 | iris.loc["ae":"ag", :] # 切片全部列 |
sepal_length | sepal_width | petal_length | petal_width | |
---|---|---|---|---|
ae | 5.0 | 3.6 | 1.4 | 0.2 |
af | 5.4 | 3.9 | 1.7 | 0.4 |
ag | 4.6 | 3.4 | 1.4 | 0.3 |
df.iloc[“indexes”, “columns”] 基于行、列的索引切片
也可以基于行或列的数字索引切片,具备 loc
的一切结构和性质。
1 | 1:3, 0:2] iris.iloc[ |
sepal_length | sepal_width | |
---|---|---|
ab | 4.9 | 3.0 |
ac | 4.7 | 3.2 |