62_Pandas有条件地提取 pandas.DataFrame 的行

62_Pandas有条件地提取 pandas.DataFrame 的行

使用query()方法根据pandas.DataFrame的列值的条件提取行。它很方便,因为您可以使用比较运算符和字符串方法以及多个条件的组合来简洁地描述条件规范。

目录

  • 使用比较运算符指定条件
  • 使用 in 运算符进行条件指定(相当于 isin())
  • 用字符串方法指定条件
    • 当有缺失值 NaN 或 None 时
  • 索引条件
  • 指定多个条件
  • 将包含空格或点的列名称用“`”括起来
  • 使用inplace参数更新原始对象

有关布尔索引的条件指定,请参阅以下文章。

  • 09_Pandas从多个条件(AND,OR,NOT)中提取行

本文示例代码的pandas版本为2.0.3版本。请注意,行为可能因版本而异。

import pandas as pd

print(pd.__version__)
# 2.0.3

df = pd.read_csv('data/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

使用比较运算符指定条件

在 pandas 中,您可以使用比较运算符来提取行,如下所示:

print(df[df['age'] < 25])
#       name  age state  point
# 0    Alice   24    NY     64
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

可以使用 query() 方法通过字符串指定类似的条件。

print(df.query('age < 25'))
#       name  age state  point
# 0    Alice   24    NY     64
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

在变量名前面加上 @ 前缀以在条件字符串中使用该变量。

val = 25
print(df.query('age < @val'))
#       name  age state  point
# 0    Alice   24    NY     64
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

可以使用两个比较运算符来指定范围,就像 Python 的条件规范一样。

print(df.query('30 <= age < 50'))
#     name  age state  point
# 1    Bob   42    CA     92
# 5  Frank   30    NY     57

还可以比较列并通过使用算术运算符进行计算来比较它们。

print(df.query('age < point / 3'))
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

==、!= 表示匹配和不匹配。请注意,条件字符串中的字符串必须加引号。

双引号 " 可以用在单引号 ’ 括起来的字符串中,单引号 ’ 可以用在双引号 " 括起来的字符串中。可以通过使用反斜杠 \ 转义来使用相同的符号。

print(df.query('state == "CA"'))
#       name  age state  point
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

使用变量时不必担心引号。

s = 'CA'
print(df.query('state != @s'))
#     name  age state  point
# 0  Alice   24    NY     64
# 3   Dave   68    TX     70
# 5  Frank   30    NY     57

使用 in 运算符进行条件指定(相当于 isin())

isin() 是一个返回 bool (True, False) 的方法,判断列 (pandas.Series) 元素是否包含在参数列表中。可以使用它来提取列中元素与特定值匹配的行。

print(df[df['state'].isin(['NY', 'TX'])])
#     name  age state  point
# 0  Alice   24    NY     64
# 3   Dave   68    TX     70
# 5  Frank   30    NY     57

在 query() 方法中使用 in 可以进行等效处理。

print(df.query('state in ["NY", "TX"]'))
#     name  age state  point
# 0  Alice   24    NY     64
# 3   Dave   68    TX     70
# 5  Frank   30    NY     57

作为一种特殊用法,列表的 == 也以同样的方式处理。

print(df.query('state == ["NY", "TX"]'))
#     name  age state  point
# 0  Alice   24    NY     64
# 3   Dave   68    TX     70
# 5  Frank   30    NY     57

还可以使用列表变量。

l = ['NY', 'TX']
print(df.query('state in @l'))
#     name  age state  point
# 0  Alice   24    NY     64
# 3   Dave   68    TX     70
# 5  Frank   30    NY     57

用字符串方法指定条件

可以使用上面的 == 或 in 指定完整字符串匹配的条件,但使用字符串方法 str.xxx() 来指定部分匹配条件。

  • 08_Pandas提取含有指定字符串的行(完全匹配,部分匹配)

参考一下的方法:

  • str.contains():包含特定字符串
  • str.endswith():以特定字符串结尾
  • str.startswith():以特定字符串开头
  • str.match():匹配正则表达式模式
    它们也可以在 query() 中使用,尽管并不比布尔索引更简洁。
print(df.query('name.str.endswith("e")'))
#       name  age state  point
# 0    Alice   24    NY     64
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70

print(df.query('name.str.contains("li")'))
#       name  age state  point
# 0    Alice   24    NY     64
# 2  Charlie   18    CA     70

可以通过使用 astype() 将除 string 之外的 dtype 类型列转换为字符串类型 str 来使用字符串方法。这也可以用 query() 指定。

print(df.query('age.astype("str").str.endswith("8")'))
#       name  age state  point
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70

当有缺失值 NaN 或 None 时

请注意,如果使用字符串方法作为缺失值 NaN 或 None 的列的条件,则会出现错误。

df.at[0, 'name'] = None
print(df)
#       name  age state  point
# 0     None   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

# print(df.query('name.str.endswith("e")'))
# ValueError: unknown type object

许多字符串方法允许参数 na 指定一个值来替换 None 或缺失值 NaN 的结果。指定 True 则提取包含缺失值的行,指定 False 则不提取包含缺失值的行。

print(df[df['name'].str.endswith('e', na=False)])
#       name  age state  point
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70

可以以与 query() 相同的方式指定参数。

print(df.query('name.str.endswith("e", na=False)'))
#       name  age state  point
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70

索引条件

可以使用index.index指定条件(行名)。

df = pd.read_csv('data/sample_pandas_normal.csv')

print(df.query('index % 2 == 0'))
#       name  age state  point
# 0    Alice   24    NY     64
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

如果索引有名称,则可以是该名称或索引。

df_name = df.set_index('name')
print(df_name)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

print(df_name.query('name.str.endswith("e")'))
#          age state  point
# name                     
# Alice     24    NY     64
# Charlie   18    CA     70
# Dave      68    TX     70

print(df_name.query('index.str.endswith("e")'))
#          age state  point
# name                     
# Alice     24    NY     64
# Charlie   18    CA     70
# Dave      68    TX     70
  • 30_Pandas.DataFrame提取(选择)指定行名和列名的行和列

指定多个条件

当用布尔索引指定多个条件时,描述如下。

  • 09_Pandas从多个条件(AND,OR,NOT)中提取行
print(df[(df['age'] < 25) & (df['point'] > 65)])
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

query()方法可以写成如下。每个条件不需要括号,AND(和)可以是 & 或 and。

print(df.query('age < 25 & point > 65'))
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

print(df.query('age < 25 and point > 65'))
#       name  age state  point
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

OR(或)、| 或或都是可接受的。

print(df.query('age < 20 | point > 80'))
#       name  age state  point
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

print(df.query('age < 20 or point > 80'))
#       name  age state  point
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 4    Ellen   24    CA     88

NOT(否定)not。

print(df.query('not age < 25 and not point > 65'))
#     name  age state  point
# 5  Frank   30    NY     57

对于三个或三个以上的条件也是如此,但结果根据顺序不同而不同,例如 & 的优先级高于 |,因此将要首先处理的部分显式括在括号中会更安全。

print(df.query('age == 24 | point > 80 & state == "CA"'))
#     name  age state  point
# 0  Alice   24    NY     64
# 1    Bob   42    CA     92
# 4  Ellen   24    CA     88

print(df.query('(age == 24 | point > 80) & state == "CA"'))
#     name  age state  point
# 1    Bob   42    CA     92
# 4  Ellen   24    CA     88

将包含空格或点的列名称用“`”括起来

使用 query() 方法时要小心列名。例如,按如下方式更改列名称。

  • 01_Pandas.DataFrame的行名和列名的修改
df.columns = ['0name', 'age.year', 'state name', 3]
print(df)
#      0name  age.year state name   3
# 0    Alice        24         NY  64
# 1      Bob        42         CA  92
# 2  Charlie        18         CA  70
# 3     Dave        68         TX  70
# 4    Ellen        24         CA  88
# 5    Frank        30         NY  57

使用作为 Python 变量名无效的列名将导致错误。例如,以数字开头的列名、包含 . 或空格的列名都是错误的。

# print(df.query('0name.str.endswith("e")'))
# SyntaxError: invalid syntax

# print(df.query('age.year < 25'))
# UndefinedVariableError: name 'age' is not defined

# print(df.query('state name == "CA"'))
# SyntaxError: invalid syntax

必须用“`”括起来。

print(df.query('`0name`.str.endswith("e")'))
#      0name  age.year state name   3
# 0    Alice        24         NY  64
# 2  Charlie        18         CA  70
# 3     Dave        68         TX  70

print(df.query('`age.year` < 25'))
#      0name  age.year state name   3
# 0    Alice        24         NY  64
# 2  Charlie        18         CA  70
# 4    Ellen        24         CA  88

print(df.query('`state name` == "CA"'))
#      0name  age.year state name   3
# 1      Bob        42         CA  92
# 2  Charlie        18         CA  70
# 4    Ellen        24         CA  88

即使数字列名包含在“`”中也会发生错误。如果使用布尔索引指定条件,则没有问题。

# print(df.query('3 > 75'))
# KeyError: False

# print(df.query('`3` > 75'))
# UndefinedVariableError: name 'BACKTICK_QUOTED_STRING_3' is not defined

print(df[df[3] > 75])
#    0name  age.year state name   3
# 1    Bob        42         CA  92
# 4  Ellen        24         CA  88

使用inplace参数更新原始对象

在到目前为止的示例中,返回一个新的 pandas.DataFrame,其中包含通过 query() 提取的行,并且原始对象保持原样。参数 inplace=True 将更改原始对象本身。

df = pd.read_csv('data/sample_pandas_normal.csv')

df.query('age > 25', inplace=True)
print(df)
#     name  age state  point
# 1    Bob   42    CA     92
# 3   Dave   68    TX     70
# 5  Frank   30    NY     57

你可能感兴趣的:(Pandas,pandas,人工智能,数据分析,python,机器学习)