关于人工智能:Pandas的数据过滤

4次阅读

共计 9505 个字符,预计需要花费 24 分钟才能阅读完成。

作者 |Amanda Iglesias Moreno
编译 |VK
起源 |Towards Datas Science

从数据帧中过滤数据是清理数据时最常见的操作之一。Pandas 提供了一系列依据行和列的地位和标签抉择数据的办法。此外,Pandas 还容许你依据列类型获取数据子集,并应用布尔索引筛选行。

在本文中,咱们将介绍从 Pandas 数据框中抉择数据子集的最常见操作:

  • 按标签抉择单列
  • 按标签抉择多列
  • 按数据类型抉择列
  • 按标签抉择一行
  • 按标签抉择多行
  • 按地位抉择一行
  • 按地位抉择多行
  • 同时抉择行和列
  • 抉择标量值
  • 应用布尔抉择抉择抉择行

另外,咱们将提供多个编码示例!

数据集

在本文中,咱们应用一个小数据集进行学习。在事实世界中,所应用的数据集要大得多;然而,用于过滤数据的过程放弃不变。

数据框蕴含公司 10 名员工的信息:(1)身份证,(2)姓名,(3)姓氏,(4)部门,(5)电话,(6)工资,(7)合同类型。

import pandas as pd

# 员工的信息
id_number = ['128', '478', '257', '299', '175', '328', '099', '457', '144', '222']
name = ['Patrick', 'Amanda', 'Antonella', 'Eduard', 'John', 'Alejandra', 'Layton', 'Melanie', 'David', 'Lewis']
surname = ['Miller', 'Torres', 'Brown', 'Iglesias', 'Wright', 'Campos', 'Platt', 'Cavill', 'Lange', 'Bellow']
division = ['Sales', 'IT', 'IT', 'Sales', 'Marketing', 'Engineering', 'Engineering', 'Sales', 'Engineering', 'Sales']
salary = [30000, 54000, 80000, 79000, 15000, 18000, 30000, 35000, 45000, 30500]
telephone = ['7366578', '7366444', '7366120', '7366574', '7366113', '7366117', '7366777', '7366579', '7366441', '7366440']
type_contract = ['permanent', 'temporary', 'temporary', 'permanent', 'internship', 'internship', 'permanent', 'temporary', 'permanent', 'permanent']

# 蕴含员工信息的 dataframe
df_employees = pd.DataFrame({'name': name, 'surname': surname, 'division': division,
                             'salary': salary, 'telephone': telephone, 'type_contract': type_contract}, index=id_number)

df_employees

1. 按标签抉择单列

要在 Pandas 中抉择一个列,咱们能够应用. 运算符和 [] 运算符。

按标签抉择单列

df[string]

上面的代码应用这两种办法拜访 salary 列。

# 应用. 符号抉择列(salary)
salary = df_employees.salary

# 应用方括号抉择列(salary)
salary_2 = df_employees['salary']

# 当抉择单个列时,咱们取得一个 Series 对象
print(type(salary))
# <class 'pandas.core.series.Series'>

print(type(salary_2))
# <class 'pandas.core.series.Series'>

salary

如上所示,当检索单个列时,后果是一个 Series 对象。为了在只抉择一列时取得一个 DataFrame 对象,咱们须要传入一个列表,而不仅仅是一个字符串。

# 通过向索引操作符传递一个字符串来获取一个 Series 对象
df_employees['salary']

# 通过将带有单个项的列表传递给索引操作符来获取 DataFrame 对象
df_employees[['salary']]

此外,重要的是要记住,当列名蕴含空格时,咱们不能应用. 表示法来拜访数据帧的特定列。如果咱们这么做了,就会产生一个语法错误。


2. 按标签抉择多列

咱们能够通过传入一个列名称如下的列表来抉择一个数据帧的多个列。

按标签抉择多列

df[list_of_strings]
# 通过将蕴含列名的列表传递给索引操作符来抉择多个列
df_employees[['division', 'salary']]

如上所示,后果是一个 DataFrame 对象,只蕴含列表中提供的列。

3. 按数据类型抉择列

咱们能够应用 pandas.DataFrame.select 类型 (include=None,exclude=None) 依据列的数据类型抉择列。该办法承受参数 include 和 exclude 中的列表或单个数据类型。

请记住,必须至多提供其中一个参数(include 或 exclude),并且它们不能蕴含重叠的元素。

按数据类型抉择列

df.select_dtypes(include=None, exclude=None)

在上面的示例中,咱们通过传入 np.number 对象增加到 include 参数。或者,咱们能够通过提供字符串 ’number‘ 作为输出来取得雷同的后果。

能够看到,select_dtypes()办法返回一个 DataFrame 对象,该对象包含 include 参数中的数据类型,而排除 exclude 参数中的数据类型。

import numpy as np

# 抉择数值列 - numpy 对象
numeric_inputs = df_employees.select_dtypes(include=np.number)

# 应用.columns 属性
numeric_inputs.columns
# Index(['salary'], dtype='object')

# 该办法返回一个 DataFrame 对象
print(type(numeric_inputs))
# <class 'pandas.core.frame.DataFrame'>

# 抉择数字列
numeric_inputs_2 = df_employees.select_dtypes(include='number')

# 应用.columns 属性
numeric_inputs_2.columns
# Index(['salary'], dtype='object')

# 该办法返回一个 DataFrame 对象
print(type(numeric_inputs_2))
# <class 'pandas.core.frame.DataFrame'>

# 可视化数据框
numeric_inputs

如前所述,select_dtypes()办法能够同时承受字符串和 numpy 对象作为输出。下表显示了在 Pandas 中援用数据类型的最罕用办法。

作为揭示,咱们能够应用 pandas.DataFrame.info 办法或应用 pandas.DataFrame.dtypes 属性。前者打印数据帧的扼要摘要,包含列名及其数据类型,而后者返回一个蕴含每个列的数据类型的序列。

# 数据框架的简要摘要,包含列名及其数据类型
df_employees.info()

# 查看列的数据类型
df_employees.dtypes

4. 按标签抉择单行

数据帧和序列不肯定有数字索引。默认状况下,索引是示意行地位的整数;然而,它也能够是字母数字字符串。在咱们以后的示例中,索引是员工的 id 号。

# 咱们能够应用.index 办法检查数据帧的索引
df_employees.index
# Index(['128', '478', '257', '299', '175', '328', '099', '457', '144', '222'], dtype='object')
# 索引是雇员的 id 号。

要按 id 号抉择一行,咱们能够应用.loc[]索引器提供一个字符串 (索引名) 作为输出。

按标签抉择单行

df.loc[string]

上面的代码显示如何抉择 id 号为 478 的员工。

# 应用.loc[]索引器抉择 id 号为 478 的员工
df_employees.loc['478']

如上所示,入选中一行时,.loc[]索引器将返回一个 Series 对象。然而,咱们也能够通过将单个元素列表传递给.loc[]办法来取得单行数据帧,如下所示。

# 应用.loc[]索引器抉择 id 号为 478 的雇员,并提供一个单元素列表
df_employees.loc[['478']]

5. 按标签抉择多行

咱们能够应用.loc[]索引器抉择多行。除单个标签外,索引器还承受一个列表或标签片段作为输出。

按标签抉择多行

df.loc[list_of_strings]
df.loc[slice_of_strings]

接下来,咱们取得蕴含 id 号为 478 和 222 的雇员的数据帧的子集,如下所示。

# 应用.loc[]索引器抉择 id 号为 478 和 222 的员工
df_employees.loc[['478', '222']]

请留神,始终蕴含.loc[]办法的完结索引,这意味着所选内容包含最初一个标签。

6. 按地位抉择单行

iloc[]索引器用于按地位索引数据帧。要应用.iloc[]属性抉择单行,咱们将行地位 (单个整数) 传递给索引器。

按地位抉择单行

df.iloc[integer]

在上面的代码块中,咱们抉择索引为 0 的行。在这种状况下,返回数据帧的第一行,因为在 Pandas 中索引从 0 开始。

# 抉择数据帧的第一行
df_employees.iloc[0]

此外,.iloc[]索引器还反对负整数 (从 - 1 开始) 作为绝对于数据帧开端的绝对地位。

# 抉择数据帧的最初一行
df_employees.iloc[-1]

如上所示,当抉择一行时,.iloc[]索引器返回一个以列名作为索引的 Series 对象。然而,正如咱们对.loc[]索引器所做的那样,咱们还能够通过以下形式将单个整数列表传递给索引器来获取数据帧。

# 抉择数据帧的最初一行
df_employees.iloc[[-1]]

最初,请记住,在尝试拜访超出边界的索引时会引发索引器谬误。

# 数据框的形态 - 10 行 6 列
df_employees.shape
# (10, 6)

# 当试图拜访一个越界的索引时,会引发一个 IndexError
df_employees.iloc[10]
# IndexError

7. 通过多个地位抉择

为了按地位提取多行,咱们将 list 或 slice 对象传递给.iloc[]索引器。

按地位抉择多行

df.iloc[list_of_integers]
df.iloc[slice_of_integers]

上面的代码块演示如何应用整数列表抉择数据帧的前五行。

# 应用列表抉择 dataframe 的前 5 行
df_employees.iloc[[0, 1, 2, 3, 4]]v

或者,咱们能够应用切片表示法失去雷同的后果。

# 应用切片抉择 dataframe 的前 5 行
df_employees.iloc[0:5]

如上所示,Python 切片规定 (半开区间) 实用于.iloc[]属性,这意味着蕴含第一个索引,但不包含完结索引。

8. 同时抉择行和列

到目前为止,咱们曾经学习了如何应用.loc[]和.iloc[]索引器按标签或地位抉择数据帧中的行。然而,这两个索引器不仅可能同时抉择行,还能够同时抉择行和列。

为此,咱们必须提供用逗号分隔的行和列标签 / 地位,如下所示:

同时抉择行和列

df.loc[row_labels, column_labels]
df.iloc[row_positions, column_positions]

其中行标签和列标签能够是单个字符串、字符串列表或字符串片段。同样,行地位和列地位能够是单个整数、整数列表或整数切片。

上面的示例演示如何应用.loc[]和.iloc[]索引器同时提取行和列。

  • 抉择标量值

咱们抉择 id 为 478 的员工的工资,办法如下。

# 按地位抉择身份证号为 478 的员工的工资
df_employees.iloc[1, 3]

# 依据标签抉择 id 号为 478 的员工的工资
df_employees.loc['478', 'salary']
# 54000

在本例中,两个索引器的输入都是整数。

  • 抉择单行和多列

咱们抉择 id 号为 478 的员工的姓名、姓氏和薪水,办法是将一个值作为第一个参数,将一个值列表作为第二个参数,从而取得一个 Series 对象。

# 按职位抉择身份证号为 478 的员工的姓名、姓氏和工资
df_employees.iloc[1, [0, 1, 3]]

# 通过标签抉择身份证号为 478 的员工的姓名、姓氏和工资
df_employees.loc['478', ['name', 'surname', 'salary']]

  • 抉择不相交的行和列

要抉择多行和多列,咱们须要向两个索引器传递两个值列表。上面的代码显示如何提取 id 号为 478 和 222 的员工的姓名、姓氏和工资。

# 按职位抉择身份证号为 478 和 222 的员工的姓名、姓氏和工资
df_employees.iloc[[1, 9], [0, 1, 3]]

# 依据标签抉择身份证号为 478 和 222 的员工的姓名、姓氏和工资
df_employees.loc[['478', '222'], ['name', 'surname', 'salary']]

与以前不同,这两个索引器的输入都是一个 DataFrame 对象。

  • 抉择间断的行和列

咱们能够应用切片表示法提取数据帧的间断行和列。上面的代码片段显示如何抉择 id 号为 128、478、257 和 299 的员工的姓名、姓氏和薪水。

# 按职位抉择 id 号为 128、478、257、299 的员工的姓名、姓氏和工资
df_employees.iloc[:4, [0, 1, 3]]

# 按标签抉择 id 号为 128、478、257、299 的员工的姓名、姓氏和工资
df_employees.loc[:'299', ['name', 'surname', 'salary']]

如上所示,咱们只应用切片表示法来提取数据帧的行,因为咱们要抉择的 id 号是间断的(索引从 0 到 3)。

肯定要记住.loc[]索引器应用一个闭合的距离,同时提取开始标签和进行标签。相同,.iloc[]索引器应用半开区间,因而不包含进行索引处的值。

9. 应用.at[]和.iat[]索引器抉择标量值

如上所述,咱们能够通过将两个用逗号分隔的字符串 / 整数传递给.loc[]和.iloc[]索引器来抉择标量值。此外,Pandas 还提供了两个优化函数来从数据帧对象中提取标量值:.at[]和.iat[]运算符。前者通过标签提取单个值,而后者通过地位拜访单个值。

通过标签和地位抉择标量值

df.at[string, string]
df.iat[integer, integer]

上面的代码显示如何应用.at[]和.iat[]索引器按标签和地位抉择 id 号为 478 的员工的工资。

# 按地位抉择身份证号为 478 的员工的工资
df_employees.iat[1, 3]

# 依据标签抉择 id 号为 478 的员工的工资
df_employees.at['478', 'salary']
# 54000

咱们能够应用 %timeit magic 函数来计算这两个 Python 语句的执行工夫。如下所示,.at[] 和.iat[]运算符比.loc[]和.iloc[]索引器快得多。

# loc 索引器的执行工夫
%timeit df_employees.loc['478', 'salary']

# at 索引器的执行工夫
%timeit df_employees.at['478', 'salary']

# iloc 索引器的执行工夫
%timeit df_employees.iloc[1, 3]

# iat 索引器的执行工夫
%timeit df_employees.iat[1, 3]

最初,必须记住,.at[]和.iat[]索引器只能用于拜访单个值,在尝试抉择数据帧的多个元素时会引发类型谬误。

# 当尝试抉择多个元素时,会引发异样
df_employees.at['478', ['name', 'surname', 'salary']]
# TypeError

10. 应用布尔抉择行

到目前为止,咱们曾经依据标签和地位过滤了数据帧中的行和列。或者,咱们也能够用布尔索引在 Pandas 中抉择一个子集。布尔抉择包含通过为每一行提供布尔值 (True 或 False) 来抉择数据帧的行。

在大多数状况下,这个布尔数组是通过将一个条件利用于一个或多个列的值来计算的,该条件的计算结果为 True 或 False,具体取决于这些值是否满足条件。然而,也能够应用其余序列、Numpy 数组、列表或 Pandas 系列手动创立布尔数组。

而后,布尔值序列放在方括号 [] 内,返回与真值相关联的行。

应用布尔抉择抉择抉择行

df[sequence_of_booleans]
依据单列值的布尔抉择

依据单列值过滤数据帧的最常见办法是应用比拟运算符。

比拟运算符计算两个操作数 (A 和 b) 之间的关系,并依据是否满足条件返回 True 或 False。下表蕴含 Python 中可用的比拟运算符。

这些比拟运算符可用于数据帧的单列,以取得布尔值序列。例如,咱们应用大于运算符确定员工的工资是否大于 45000,如下所示。

# 工资超过 45000 的员工
df_employees['salary'] > 45000

输入是一系列布尔函数,其中工资高于 45000 为真,低于或等于 45000 为假。正如你可能留神到的那样,boolean 系列具备与原始数据帧雷同的索引(id 编号)。

能够将此序列传递给索引运算符[],以仅返回后果为 True 的行。

# 抉择工资高于 45000 的员工
df_employees[df_employees['salary'] > 45000]

如上所示,咱们取得了一个数据帧对象,其中只蕴含工资高于 45000 的员工。

依据多列值的布尔抉择

之前,咱们曾经依据一个条件过滤了一个数据帧。然而,咱们也能够应用逻辑运算符将多个布尔表达式组合在一起。

在 Python 中,有三个逻辑运算符:and、or 和 not。然而,这些关键字在 Pandas 中不可用于组合多个布尔条件。而是应用以下运算符。

上面的代码展现了如何抉择薪水高于 45000 的员工,以及有一份永恒合同,其中蕴含两个布尔表达式和逻辑运算符 &。

# 抉择工资高于 45000 并有长期合同的员工
df_employees[(df_employees['salary'] > 45000) & (df_employees['type_contract'] == 'permanent')]

如你所知,在 Python 中,比拟运算符的优先级高于逻辑运算符。然而,它不适用于逻辑运算符优先于比拟运算符的 panda。因而,咱们须要将每个布尔表达式包装在括号中以防止谬误。

应用 Pandas 办法的布尔抉择

Pandas 提供了一系列返回布尔值序列的内置函数,它是联合比拟运算符和逻辑运算符的更简单布尔表达式的一个有吸引力的代替计划。

  • isin 办法

这个 pandas.Series.isin 办法承受一系列值,并在序列中与列表中的值匹配的地位返回 True。

此办法容许咱们查看列中是否存在一个或多个元素,而无需应用逻辑运算符或。上面的代码显示如何应用逻辑运算符 or 和 isin 办法抉择具备永恒或长期合同的员工。

# 应用逻辑操作符或抉择具备永恒或长期合同的员工
df_employees[(df_employees['type_contract'] == 'temporary') | (df_employees['type_contract'] == 'permanent')]

# 应用 isin 办法抉择有永恒或长期合同的员工
df_employees[df_employees['type_contract'].isin(['temporary', 'permanent'])]

如你所见,isin 办法在查看同一列中的多个或条件时十分不便。另外,它更快!

# 应用逻辑运算符 | 执行工夫
%timeit df_employees[(df_employees['type_contract'] == 'temporary') | (df_employees['type_contract'] == 'permanent')]

# isin 办法的执行工夫
%timeit df_employees[df_employees['type_contract'].isin(['temporary', 'permanent'])]

between 办法

这个熊猫系列办法承受两个用逗号分隔的标量,它们示意一个值范畴的高低边界,并在该范畴内的地位返回 True。

以下代码抉择工资高于或等于 30000 且小于或等于 80000 的员工。

# 薪资高于或等于 30000,低于或等于 80000 的员工
df_employees[df_employees['salary'].between(30000, 80000)]

如你所见,这两个边界 (30000 和 80000) 都包含在内。要排除它们,咱们必须按以下形式传递 inclusive=False 参数。

# 薪资在 3 万以上,8 万以下的员工
df_employees[df_employees['salary'].between(30000, 80000, inclusive=False)]

正如你可能留神到的,下面的代码相当于编写两个布尔表达式,并应用逻辑运算符 and 对它们求值。

# 薪资高于或等于 30000,低于或等于 80000 的员工
df_employees[(df_employees['salary']>=30000) & (df_employees['salary']<=80000)]
  • 字符串办法

此外,咱们还能够将布尔索引与字符串办法一起应用,只有它们返回布尔值序列。

例如 pandas.Series.str.contains 办法查看列的所有元素中是否存在子字符串,并返回一系列布尔值,咱们能够将这些布尔值传递给索引运算符以筛选数据帧。

上面的代码显示如何抉择蕴含 57 的所有电话号码。

# 抉择所有蕴含 57 的电话号码
df_employees[df_employees['telephone'].str.contains('57')]

当 contains 办法计算子字符串是否蕴含在序列的每个元素中。pandas.Series.str.startswith 函数查看字符串结尾是否存在子字符串。同样地 pandas.Series.str.endswith 测试字符串开端是否存在子字符串。

以下代码显示如何抉择姓名以“A”结尾的员工。

# 抉择名字以“A”结尾的员工
df_employees[df_employees['name'].str.startswith('A')]

摘要

在本文中,咱们学习从 Dataframe 中抉择子集。此外,咱们还提供了多个应用示例。当初!当初是时候在清理你本人的数据时利用这些技术了!

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

正文完
 0