Pandas筛选操作详解 | 轻松玩转Pandas(8)

2018年7月22日11:30:17 发表评论 85

教你学会 Pandas 不是我的目的,教你轻松玩转 Pandas 才是我的目的。我会通过一系列实例来带入 Pandas 的知识点,让你在学习 Pandas 的路上不再枯燥。

声明:我所写的轻松玩转 Pandas 教程都是免费的,如果对你有帮助,你可以持续关注我。

在数据处理过程中,经常会遇到要筛选不同要求的数据,通过 Pandas 可以轻松实现,这一篇我们来看下如何使用 Pandas 来完成数据筛选吧。

# 导入相关库
import numpy as np
import pandas as pd

Pandas 中除了支持 Python 和 Numpy 的索引运算符[]和属性运算符.来访问数据之外,还有很多其他的方式来访问数据,我们一起来看看吧。

index = pd.Index(data=["Tom", "Bob", "Mary", "James", "Andy", "Alice"], name="name")

data = {
    "age": [18, 30, np.nan, 40, np.nan, 30],
    "city": ["Bei Jing ", "Shang Hai ", "Guang Zhou", "Shen Zhen", np.nan, " "],
    "sex": [None, "male", "female", "male", np.nan, "unknown"],
    "birth": ["2000-02-10", "1988-10-17", None, "1978-08-08", np.nan, "1988-10-17"]
}

user_info = pd.DataFrame(data=data, index=index)

# 将出生日期转为时间戳
user_info["birth"] = pd.to_datetime(user_info.birth)
user_info
age birth city sex
name
Tom 18.0 2000-02-10 Bei Jing None
Bob 30.0 1988-10-17 Shang Hai male
Mary NaN NaT Guang Zhou female
James 40.0 1978-08-08 Shen Zhen male
Andy NaN NaT NaN NaN
Alice 30.0 1988-10-17 unknown

字典式 get 访问

我们都知道,Python 中的字典要获取 value 时可以通过 get 方法来获取,对于 Series 和 DataFrame 也一样,他们一样可以通过 get 方法来获取。

# 获取得到所有年龄相关的这一列的信息,结果为一个 Series
user_info.get("age")
name
Tom      18.0
Bob      30.0
Mary      NaN
James    40.0
Andy      NaN
Alice    30.0
Name: age, dtype: float64
# 从包含所有的年龄信息的 Series 中得到 Tom 的年龄
user_info.get("age").get("Tom")
18.0

属性访问

除了可以通过 get 方法来获取数据之外,还可以通过属性的方式来访问,同样完成上面的功能,来看下如何通过属性访问的方式来实现。

# 获取得到所有年龄相关的这一列的信息,结果为一个 Series
user_info.age
name
Tom      18.0
Bob      30.0
Mary      NaN
James    40.0
Andy      NaN
Alice    30.0
Name: age, dtype: float64
# 从包含所有的年龄信息的 Series 中得到 Tom 的年龄
user_info.age.Tom
18.0

切片操作

在学习 Python 时,会发现列表的切片操作非常地方便,Series 和 DataFrame 同样也有切片操作。

对于 Series 来说,通过切片可以完成选择指定的行,对于 Series 来说,通过切片可以完成选择指定的行或者列,来看看怎么玩吧。

# 获取年龄的前两行
user_info.age[:2]
name
Tom    18.0
Bob    30.0
Name: age, dtype: float64
# 获取所有信息的前两行
user_info[:2]
age birth city sex
name
Tom 18.0 2000-02-10 Bei Jing None
Bob 30.0 1988-10-17 Shang Hai male
# 所有信息每两行选择一次数据
user_info[::2]
age birth city sex
name
Tom 18.0 2000-02-10 Bei Jing None
Mary NaN NaT Guang Zhou female
Andy NaN NaT NaN NaN
# 对所有信息进行反转
user_info[::-1]
age birth city sex
name
Alice 30.0 1988-10-17 unknown
Andy NaN NaT NaN NaN
James 40.0 1978-08-08 Shen Zhen male
Mary NaN NaT Guang Zhou female
Bob 30.0 1988-10-17 Shang Hai male
Tom 18.0 2000-02-10 Bei Jing None

上面都是筛选行,如何筛选 DataFrame 中的列呢?

只需要将列名传入切片即可完成筛选。

user_info["age"]
name
Tom      18.0
Bob      30.0
Mary      NaN
James    40.0
Andy      NaN
Alice    30.0
Name: age, dtype: float64

如何筛选出多列的数据呢?只需要将对应的列名传入组成一个列表,传入切片中即可。

user_info[["city", "age"]]
city age
name
Tom Bei Jing 18.0
Bob Shang Hai 30.0
Mary Guang Zhou NaN
James Shen Zhen 40.0
Andy NaN NaN
Alice 30.0

可以看到,列表中的列名的顺序会影响最后的结果。

通过数字筛选行和列

通过切片操作可以完成筛选行或者列,如何同时筛选出行和列呢?

通过 iloc 即可实现, iloc 支持传入行和列的筛选器,并用 , 隔开。无论是行或者里筛选器,都可以为以下几种情况:

  • 一个整数,如 2
  • 一个整数列表,如 [2, 1, 4]
  • 一个整数切片对象,如 2:4
  • 一个布尔数组
  • 一个callable

先来看下前3种的用法。

# 筛选出第一行数据
user_info.iloc[0]
age                       18
birth    2000-02-10 00:00:00
city               Bei Jing 
sex                     None
Name: Tom, dtype: object
# 筛选出第二行第一列的数据
user_info.iloc[1, 0]
30.0
# 筛选出第二行、第一行、第三行对应的第一列的数据
user_info.iloc[[1, 0, 2], 0]
name
Bob     30.0
Tom     18.0
Mary     NaN
Name: age, dtype: float64
# 筛选出第一行至第三行以及第一列至第二列的数据
user_info.iloc[0:3, 0:2]
age birth
name
Tom 18.0 2000-02-10
Bob 30.0 1988-10-17
Mary NaN NaT
# 筛选出第一列至第二列的数据
user_info.iloc[:, 0:2]
age birth
name
Tom 18.0 2000-02-10
Bob 30.0 1988-10-17
Mary NaN NaT
James 40.0 1978-08-08
Andy NaN NaT
Alice 30.0 1988-10-17

通过名称筛选行和列

虽然通过 iloc 可以实现同时筛选出行和列,但是它接收的是输入,非常不直观, 通过 loc 可实现传入名称来筛选数据,loc 支持传入行和列的筛选器,并用 , 隔开。无论是行或者里筛选器,都可以为以下几种情况:

  • 一个索引的名称,如:"Tom"
  • 一个索引的列表,如:["Bob", "Tom"]
  • 一个标签范围,如:"Tom": "Mary"
  • 一个布尔数组
  • 一个callable

先来看下前3种的用法。

# 筛选出名称为 Tom 的数据一行数据
user_info.loc["Tom"]
age                       18
birth    2000-02-10 00:00:00
city               Bei Jing 
sex                     None
Name: Tom, dtype: object
# 筛选出名称为 Tom 的年龄
user_info.loc["Tom", "age"]
18.0
# 筛选出名称在 ["Bob", "Tom"] 中的两行数据
user_info.loc[["Bob", "Tom"]]
age birth city sex
name
Bob 30.0 1988-10-17 Shang Hai male
Tom 18.0 2000-02-10 Bei Jing None
# 筛选出索引名称在 Tom 到 Mary 之间的数据
user_info.loc["Tom": "Mary"]
age birth city sex
name
Tom 18.0 2000-02-10 Bei Jing None
Bob 30.0 1988-10-17 Shang Hai male
Mary NaN NaT Guang Zhou female
# 筛选出年龄这一列数据
user_info.loc[:, ["age"]]
age
name
Tom 18.0
Bob 30.0
Mary NaN
James 40.0
Andy NaN
Alice 30.0
# 筛选出所有 age 到 birth 之间的这几列数据
user_info.loc[:, "age": "birth"]
age birth
name
Tom 18.0 2000-02-10
Bob 30.0 1988-10-17
Mary NaN NaT
James 40.0 1978-08-08
Andy NaN NaT
Alice 30.0 1988-10-17

你可能已经发现了,通过名称来筛选时,传入的切片是左右都包含的。

布尔索引

通过布尔操作我们一样可以进行筛选操作,布尔操作时,& 对应 and| 对应 or~ 对应 not

当有多个布尔表达式时,需要通过小括号来进行分组。

user_info[user_info.age > 20]
age birth city sex
name
Bob 30.0 1988-10-17 Shang Hai male
James 40.0 1978-08-08 Shen Zhen male
Alice 30.0 1988-10-17 unknown
# 筛选出年龄在20岁以上,并且性别为男性的数据
user_info[(user_info.age > 20) & (user_info.sex == "male")]
age birth city sex
name
Bob 30.0 1988-10-17 Shang Hai male
James 40.0 1978-08-08 Shen Zhen male
# 筛选出性别不为 unknown 的数据
user_info[~(user_info.sex == "unknown")]
age birth city sex
name
Tom 18.0 2000-02-10 Bei Jing None
Bob 30.0 1988-10-17 Shang Hai male
Mary NaN NaT Guang Zhou female
James 40.0 1978-08-08 Shen Zhen male
Andy NaN NaT NaN NaN

除了切片操作可以实现之外, loc 一样可以实现。

user_info.loc[user_info.age > 20, ["age"]]
age
name
Bob 30.0
James 40.0
Alice 30.0

isin 筛选

Series 包含了 isin 方法,它能够返回一个布尔向量,用于筛选数据。

# 筛选出性别属于 male 和 female的数据
user_info[user_info.sex.isin(["male", "female"])]
age birth city sex
name
Bob 30.0 1988-10-17 Shang Hai male
Mary NaN NaT Guang Zhou female
James 40.0 1978-08-08 Shen Zhen male

对于索引来说,一样可以使用 isin 方法来筛选。

user_info[user_info.index.isin(["Bob"])]
age birth city sex
name
Bob 30.0 1988-10-17 Shang Hai male

通过Callable筛选

lociloc、切片操作都支持接收一个 callable 函数,callable必须是带有一个参数(调用Series,DataFrame)的函数,并且返回用于索引的有效输出。

user_info[lambda df: df["age"] > 20]
age birth city sex
name
Bob 30.0 1988-10-17 Shang Hai male
James 40.0 1978-08-08 Shen Zhen male
Alice 30.0 1988-10-17 unknown
user_info.loc[lambda df: df.age > 20, lambda df: ["age"]]
age
name
Bob 30.0
James 40.0
Alice 30.0
user_info.iloc[lambda df: [0, 5], lambda df: [0]]
age
name
Tom 18.0
Alice 30.0

知识星球

我的知识星球刚刚开通,星球的核心就是:实战、实战、再实战,星球的详细介绍见:如何花更少的时间,做更多的 AI 项目,需要实战的小伙伴可以加入一波~


想要学习更多关于人工智能的知识,请关注公众号:AI派

这里我将整篇文章的内容整理成了pdf,想要pdf文件的可以在公众号后台回复关键字:pandas

  • 个人微信号
  • 添加时请备注“脑洞大开读者”
  • weinxin
  • 微信公众号
  • 关注会有更多精彩内容!
  • weinxin

发表评论

您必须登录才能发表评论!