Pandas df.query() 函数
query() 是 Pandas 中非常实用的数据筛选函数,它允许使用类似 SQL 的字符串表达式来筛选数据。相比于传统的布尔索引方式,query() 的语法更加简洁直观,特别适合处理复杂的筛选条件。
在数据分析工作中,经常需要根据各种条件筛选数据。query() 函数将筛选条件写成字符串形式,就像写 SQL 查询一样,这对于熟悉 SQL 的用户来说非常友好。同时,它也支持使用 Python 变量和函数,使动态筛选成为可能。
基本语法与参数
query() 是 DataFrame 的方法,通过点运算符 . 来调用。它接受一个字符串参数,该字符串包含筛选表达式。
语法格式
DataFrame.query(expr, inplace=False, **kwargs)
参数说明
| 参数 | 类型 | 是否必填 | 说明 | 默认值 |
|---|---|---|---|---|
| expr | str | 必填 | 筛选表达式,类似于 SQL 的 WHERE 子句。 | - |
| inplace | bool | 可选 | 是否在原 DataFrame 上直接修改。 | False |
返回值说明
- 返回值类型: 返回一个新的 DataFrame,包含满足筛选条件的行。
- 不修改原数据: 默认情况下,原 DataFrame 保持不变。
实例
让我们通过丰富的例子全面掌握 query() 的用法。
示例 1:基础用法 - 单条件筛选
最简单的 query() 用法是使用单个条件进行筛选。
实例
import pandas as pd
# 创建示例 DataFrame
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'age': [18, 19, 17, 18, 20, 19, 18],
'score': [85, 92, 78, 90, 88, 95, 82],
'grade': ['A', 'A', 'B', 'A', 'B', 'A', 'B']
}
df = pd.DataFrame(data)
print("原始 DataFrame:")
print(df)
print()
# 筛选分数大于 85 的学生
print("分数大于 85 的学生:")
print(df.query('score > 85'))
print()
# 筛选年龄等于 18 的学生
print("年龄等于 18 的学生:")
print(df.query('age == 18'))
print()
# 筛选等级为 A 的学生
print("等级为 A 的学生:")
print(df.query('grade == "A"'))
# 创建示例 DataFrame
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'age': [18, 19, 17, 18, 20, 19, 18],
'score': [85, 92, 78, 90, 88, 95, 82],
'grade': ['A', 'A', 'B', 'A', 'B', 'A', 'B']
}
df = pd.DataFrame(data)
print("原始 DataFrame:")
print(df)
print()
# 筛选分数大于 85 的学生
print("分数大于 85 的学生:")
print(df.query('score > 85'))
print()
# 筛选年龄等于 18 的学生
print("年龄等于 18 的学生:")
print(df.query('age == 18'))
print()
# 筛选等级为 A 的学生
print("等级为 A 的学生:")
print(df.query('grade == "A"'))
运行结果:
原始 DataFrame:
name age score grade
0 Alice 18 85 A
1 Bob 19 92 A
2 Charlie 17 78 B
3 David 18 90 A
4 Eve 20 88 B
5 Frank 19 95 A
6 Grace 18 82 B
分数大于 85 的学生:
name age score grade
1 Bob 19 92 A
3 David 18 90 A
4 Eve 20 88 B
5 Frank 19 95 A
年龄等于 18 的学生:
name age score grade
0 Alice 18 85 A
3 David 18 90 A
6 Grace 18 82 B
等级为 A 的学生:
name age score grade
0 Alice 18 85 A
1 Bob 19 92 A
3 David 18 90 A
5 Frank 19 95 A
代码解析:
- 筛选条件放在引号中,使用类似 SQL 的语法。
- 数值比较使用
>,==,<等运算符。 - 字符串比较使用双引号或单引号。
示例 2:复合条件筛选
query() 支持使用逻辑运算符组合多个条件。
实例
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'age': [18, 19, 17, 18, 20, 19, 18],
'score': [85, 92, 78, 90, 88, 95, 82],
'grade': ['A', 'A', 'B', 'A', 'B', 'A', 'B']
}
df = pd.DataFrame(data)
# 使用 AND 条件:分数大于 85 且年龄小于 19
print("分数大于 85 且年龄小于 19 的学生:")
print(df.query('score > 85 and age 90'))
print()
# 使用 NOT 条件:等级不为 A
print("等级不为 A 的学生:")
print(df.query('not grade == "A"'))
print()
# 复杂的复合条件
print("年龄在 18 到 20 之间且分数不等于 88 的学生:")
print(df.query('age >= 18 and age <= 20 and score != 88'))
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'age': [18, 19, 17, 18, 20, 19, 18],
'score': [85, 92, 78, 90, 88, 95, 82],
'grade': ['A', 'A', 'B', 'A', 'B', 'A', 'B']
}
df = pd.DataFrame(data)
# 使用 AND 条件:分数大于 85 且年龄小于 19
print("分数大于 85 且年龄小于 19 的学生:")
print(df.query('score > 85 and age 90'))
print()
# 使用 NOT 条件:等级不为 A
print("等级不为 A 的学生:")
print(df.query('not grade == "A"'))
print()
# 复杂的复合条件
print("年龄在 18 到 20 之间且分数不等于 88 的学生:")
print(df.query('age >= 18 and age <= 20 and score != 88'))
运行结果:
分数大于 85 且年龄小于 19 的学生:
name age score grade
3 David 18 90 A
5 Frank 19 95 A
等级为 A 或分数大于 90 的学生:
name age score grade
1 Bob 19 92 A
3 David 18 90 A
5 Frank 19 95 A
等级不为 A 的学生:
name age score grade
2 Charlie 17 78 B
4 Eve 20 88 B
6 Grace 18 82 B
年龄在 18 到 20 之间且分数不等于 88 的学生:
name age score grade
0 Alice 18 85 A
1 Bob 19 92 A
3 David 18 90 A
5 Frank 19 95 A
代码解析:
- 使用
and表示逻辑与运算。 - 使用
or表示逻辑或运算。 - 使用
not表示逻辑非运算。 - 复合条件可以任意组合,形成复杂的筛选逻辑。
示例 3:使用 Python 变量
query() 支持在表达式中使用 Python 变量,这在动态查询中非常有用。
实例
import pandas as pd
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'age': [18, 19, 17, 18, 20, 19, 18],
'score': [85, 92, 78, 90, 88, 95, 82],
'grade': ['A', 'A', 'B', 'A', 'B', 'A', 'B']
}
df = pd.DataFrame(data)
# 使用 @ 符号引用 Python 变量
min_score = 85
target_grade = 'A'
print("使用变量筛选 - 分数大于 {}:".format(min_score))
print(df.query('score > @min_score'))
print()
print("使用变量筛选 - 等级为 '{}':".format(target_grade))
print(df.query('grade == @target_grade'))
print()
# 使用列表作为变量
target_grades = ['A', 'B']
print("等级在 {} 中的学生:".format(target_grades))
print(df.query('grade in @target_grades'))
print()
# 使用 Python 函数
def get_average_score(df):
return df['score'].mean()
print("分数高于平均分的学生:")
print(df.query('score > @get_average_score(df)'))
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'age': [18, 19, 17, 18, 20, 19, 18],
'score': [85, 92, 78, 90, 88, 95, 82],
'grade': ['A', 'A', 'B', 'A', 'B', 'A', 'B']
}
df = pd.DataFrame(data)
# 使用 @ 符号引用 Python 变量
min_score = 85
target_grade = 'A'
print("使用变量筛选 - 分数大于 {}:".format(min_score))
print(df.query('score > @min_score'))
print()
print("使用变量筛选 - 等级为 '{}':".format(target_grade))
print(df.query('grade == @target_grade'))
print()
# 使用列表作为变量
target_grades = ['A', 'B']
print("等级在 {} 中的学生:".format(target_grades))
print(df.query('grade in @target_grades'))
print()
# 使用 Python 函数
def get_average_score(df):
return df['score'].mean()
print("分数高于平均分的学生:")
print(df.query('score > @get_average_score(df)'))
运行结果:
使用变量筛选 - 分数大于 85:
name age score grade
1 Bob 19 92 A
3 David 18 90 A
4 Eve 20 88 B
5 Frank 19 95 A
使用变量筛选 - 等级为 'A':
name age score grade
0 Alice 18 85 A
1 Bob 19 92 A
3 David 18 90 A
5 Frank 19 95 A
等级在 ['A', 'B'] 中的学生:
name age score grade
0 Alice 18 85 A
1 Bob 19 92 A
2 Charlie 17 78 B
3 David 18 90 A
4 Eve 20 88 B
5 Frank 19 95 A
6 Grace 18 82 B
分数高于平均分的学生:
name age score grade
1 Bob 19 92 A
3 David 18 90 A
5 Frank 19 95 A
代码解析:
- 使用
@符号可以在查询表达式中引用 Python 变量。 - 可以直接使用 Python 列表进行
in判断。 - 可以调用 Python 函数来计算动态阈值。
示例 4:字符串操作
query() 还支持一些常见的字符串操作。
实例
import pandas as pd
# 创建带有字符串列的 DataFrame
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai', 'Beijing', 'Shenzhen'],
'score': [85, 92, 78, 90, 88, 95, 82]
}
df = pd.DataFrame(data)
# 筛选特定城市的记录
print("在北京的学生:")
print(df.query('city == "Beijing"'))
print()
# 字符串包含判断(使用 in)
print("在上海或北京的学生:")
print(df.query('city in ["Shanghai", "Beijing"]'))
print()
# 使用 @ 引用包含字符串的变量
target_city = 'Guangzhou'
print("在 {} 的学生:".format(target_city))
print(df.query('city == @target_city'))
# 创建带有字符串列的 DataFrame
data = {
'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai', 'Beijing', 'Shenzhen'],
'score': [85, 92, 78, 90, 88, 95, 82]
}
df = pd.DataFrame(data)
# 筛选特定城市的记录
print("在北京的学生:")
print(df.query('city == "Beijing"'))
print()
# 字符串包含判断(使用 in)
print("在上海或北京的学生:")
print(df.query('city in ["Shanghai", "Beijing"]'))
print()
# 使用 @ 引用包含字符串的变量
target_city = 'Guangzhou'
print("在 {} 的学生:".format(target_city))
print(df.query('city == @target_city'))
运行结果:
在北京的学生:
name city score
0 Alice Beijing 85
2 Charlie Beijing 78
5 Frank Beijing 95
在上海或北京的学生:
name city score
0 Alice Beijing 85
1 Bob Shanghai 92
2 Charlie Beijing 78
4 Eve Shanghai 88
5 Frank Beijing 95
在 Guangzhou 的学生:
name city score
3 David Guangzhou 90
代码解析:
query()支持字符串的相等比较。- 可以使用
in关键字判断元素是否在列表中。 - 可以使用
@引用字符串变量。
示例 5:处理列名中有空格或特殊字符的情况
如果列名包含空格或特殊字符,可以使用反引号 `` ` `` 包裹列名。
实例
import pandas as pd
# 创建列名包含空格的 DataFrame
data = {
'student name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'score': [85, 92, 78, 90, 88],
'pass status': [True, True, False, True, True]
}
df = pd.DataFrame(data)
print("原始 DataFrame(列名包含空格):")
print(df)
print()
# 使用反引号包裹列名
print("分数大于 85 的学生:")
print(df.query('`score` > 85'))
print()
print("通过状态为 True 的学生:")
print(df.query('`pass status` == True'))
print()
# 也可以用这个方法处理保留字作为列名
df2 = pd.DataFrame({
'class': ['A', 'B', 'A', 'B', 'A'],
'def': [1, 2, 3, 4, 5] # def 是 Python 保留字
})
print("使用保留字作为列名:")
print(df2.query('`def` > 3'))
# 创建列名包含空格的 DataFrame
data = {
'student name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'score': [85, 92, 78, 90, 88],
'pass status': [True, True, False, True, True]
}
df = pd.DataFrame(data)
print("原始 DataFrame(列名包含空格):")
print(df)
print()
# 使用反引号包裹列名
print("分数大于 85 的学生:")
print(df.query('`score` > 85'))
print()
print("通过状态为 True 的学生:")
print(df.query('`pass status` == True'))
print()
# 也可以用这个方法处理保留字作为列名
df2 = pd.DataFrame({
'class': ['A', 'B', 'A', 'B', 'A'],
'def': [1, 2, 3, 4, 5] # def 是 Python 保留字
})
print("使用保留字作为列名:")
print(df2.query('`def` > 3'))
运行结果:
原始 DataFrame(列名包含空格): student name score pass status 0 Alice 85 True 1 Bob 92 True 2 Charlie 78 False 3 David 90 True 4 Eve 88 True 分数大于 85 的学生: student name score pass status 1 Bob 92 True 3 David 90 True 4 Eve 88 True 通过状态为 True 的学生: student name score pass status 0 Alice 85 True 1 Bob 92 True 3 David 90 True 4 Eve 88 True 使用保留字作为列名: class def 3 B 4 4 A 5
代码解析:
- 通过使用反引号,可以处理列名包含空格或与 Python 保留字冲突的情况。
`score`和`pass status`用于引用列名。`def`展示了如何处理 Python 保留字作为列名。
注意事项
query()表达式中的列名必须是有效的 Python 标识符,或者用反引号包裹。- 字符串比较可以使用单引号或双引号。
- 使用
@符号引用 Python 变量。 - 对于大型 DataFrame,
query()的性能通常优于传统的布尔索引。 - 如果筛选表达式中有保留字或特殊字符,必须使用反引号。
提示:
query()特别适合需要动态构建筛选条件的场景,比如根据用户输入或配置文件来筛选数据。结合 Python 的字符串格式化功能,可以实现非常灵活的数据查询。
小结
query() 是 Pandas 中强大的数据筛选函数,它提供了类似 SQL 的查询语法,使复杂的条件筛选变得更加简洁和易读。
它的主要优势包括:语法简洁直观、支持复合逻辑运算、支持 Python 变量和函数、可以处理特殊列名。在实际数据分析中,特别是需要动态构建筛选条件时,query() 是一个非常实用的工具。

Pandas 常用函数