0%

[Python] 经验总结 1:数据框的切片

每个人都知道 Python 是一种高效、简洁、优雅的语言。然而 Python 也有很多坑,现在老宅开一个新系列,分享老宅在学习和实践中总结的经验和教训,不定期分享。

第一个经验就是要吐槽数据框的切片。Python 有很多第三方的模块(比如 pandas 这样的数据科学神器),对提升 Python 的实用性贡献很大。然而模块多就有一个副作用:语法的不一致性。老宅在学习 pandas 的过程中就被数据框切片的复杂语法搞得挠头。

本文参考了 http://chris.friedline.net/2015-12-15-rutgers/lessons/python2/02-index-slice-subset.html,特此致谢。

数据框的切片,是在列表的切片的基础上发展起来的。不过列表是一维,数据框是二维,因此数据框切片有自己独特的方法。所以数据框的切片有两个风格:原生风格和 pandas 风格(这两个风格是老宅自己总结的…)。在总结以前,我们先构建数据集:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import pandas as pd
>>> from sklearn.datasets import load_iris # 载入 iris 数据集模块
>>> iris = pd.DataFrame(load_iris()["data"]) # 载入 iris 数据集并转化为列表
>>> iris.columns = ["sepal_length", "sepal_width",
... "petal_length", "petal_width"] # 定义列名
>>> from string import ascii_lowercase # 载入字母表
>>> idx = []
>>> for i in ascii_lowercase:
... for j in ascii_lowercase:
... idx.append(i + j)
# 创建字母表排列组合
>>> iris.index = idx[:150] # 定义行名
>>> iris.head()
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
2
3
4
5
6
>>> iris.sepal_length[1:5]
ab 4.9
ac 4.7
ad 4.6
ae 5.0
Name: sepal_length, dtype: float64

这个方法不需要用 "" 括上列,非常方便。不过这样有个潜在的局限:如果列名里有空格,这个方法就不好用了,就要用下面的方法。

  • df["column"] 方法

这个方法的好处是引号内可以有特殊符号,比如空格。这样切片稍微麻烦一点,但是还可以接受。

  • df[["column"]] 方法

这个方法与上面一样都用来切片单列。有什么不同呢?请看下面的例子:

1
2
3
4
5
6
7
8
9
>>> iris["sepal_length"][1:5]

ab 4.9
ac 4.7
ad 4.6
ae 5.0
Name: sepal_length, dtype: float64

>>> iris[["sepal_length"]][1:5]
sepal_length
ab 4.9
ac 4.7
ad 4.6
ae 5.0

单中括号和双中括号的区别在于单中括号返回的是序列,而双中括号返回的是数据框。

切片多列

  • df[["column1", "columns2"...]] 方法
    因为多个列组合在一起是一个数据框,所以必须使用双中括号来切片。列名要用引号括起来。
  • df[list] 方法
    这里就体现出不一致性了:假如我们先将想要切片的列放入一个列表,就可以使用单中括号,而且不需要使用引号。
    1
    2
    >>> lst = ["sepal_length","petal_length"]
    >>> 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
    >>> iris[1:5]
    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
    >>> iris["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

行切片还有一个列切片不具备的功能:切片连续的行。如果数据框的行名和列名不一致,pandas 会自动判断你在切片行还是列。如果一致嘛…pandas 就不知所措了。这时候就要用到下面的 pandas 风格切片。

pandas 风格切片

df.loc[“indexes”, “columns”] 基于行、列的名称切片

注意行和列都是用的复数形式,意味着可以同时切片多行或多列。同时也可以切片范围内的行或列,使用 : 即可。

1
>>> iris.loc["ae":"ag", ["sepal_length","petal_length"]]
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
>>> iris.iloc[1:3, 0:2]
sepal_length sepal_width
ab 4.9 3.0
ac 4.7 3.2

欢迎关注我的其它发布渠道