query() 方法
使用 query() 将可读的筛选表达式写成字符串,借助 @ 在查询中使用 Python 变量,并串联多个筛选条件。
query() 方法 是 CoddyKit 上的免费 Pandas & NumPy Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Pandas & NumPy Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Pandas & NumPy Academy 课程共包含 4 节课。
为什么使用 query()?
Pandas 的布尔索引功能很强大,但组合多个条件时,表达式可能会变得冗长。query() 方法允许您将筛选表达式写成普通字符串,许多人认为这样更易读,尤其是有 SQL 背景的用户。您可以不写 df[(df['age'] > 30) & (df['salary'] > 50000)],而写成 df.query('age > 30 and salary > 50000')。
查询字符串会根据 DataFrame 的列名进行求值,因此列名在字符串中相当于变量名。
import pandas as pd
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Carol', 'Dave'],
'age': [25, 35, 28, 45],
'salary': [50000, 90000, 70000, 120000]
})
# Boolean indexing style
result1 = df[(df['age'] > 27) & (df['salary'] > 60000)]
# Equivalent query() style
result2 = df.query('age > 27 and salary > 60000')
print(result2)
# name age salary
# 1 Bob 35 90000
# 2 Carol 28 70000查询字符串中的语法规则
在查询字符串中,您可以使用标准的 Python 比较运算符(>、<、==、!=、>=、<=)以及逻辑连接词 and、or、not。与普通的布尔索引不同,这里可以使用英文单词,不需要使用与号或竖线。
包含空格或与 Python 关键字冲突的列名必须使用反引号括起来:df.query('`first name` == "Alice"')。
import pandas as pd
df = pd.DataFrame({
'product': ['A', 'B', 'C', 'D'],
'price': [10, 200, 50, 300],
'in_stock': [True, False, True, True]
})
# Use 'and', 'or', 'not' in query strings
result = df.query('price > 40 and in_stock == True')
print(result)
# product price in_stock
# 2 C 50 True
# 3 D 300 True使用 @ 引用 Python 变量
query() 的一个重要特性是,可以使用 @ 前缀引用外围作用域中的 Python 变量。这样可以方便地参数化筛选条件:先计算阈值并将其存入变量,然后在查询字符串中使用 @variable_name,而不是将数值直接写死。
这种写法对于在运行时接收筛选参数的函数非常有用。
import pandas as pd
df = pd.DataFrame({
'city': ['NYC', 'LA', 'Chicago', 'Houston'],
'population': [8336817, 3979576, 2693976, 2320268]
})
min_pop = 3_000_000 # Python variable
# Use @ to inject the variable into the query
result = df.query('population > @min_pop')
print(result)
# city population
# 0 NYC 8336817
# 1 LA 3979576串联多个 query() 调用
由于 query() 会返回一个新的 DataFrame,因此您可以串联多个 query 调用,或在数据处理流水线中将它们与其他 Pandas 方法组合使用。串联写法会将每个筛选步骤放在单独的一行中,使逻辑更易于阅读、调试和修改。
您还可以将 query() 与 .groupby()、.sort_values() 或 .head() 等方法串联起来,构建简洁的分析流水线。
import pandas as pd
df = pd.DataFrame({
'region': ['North', 'South', 'North', 'East', 'South'],
'year': [2022, 2022, 2023, 2023, 2023],
'revenue': [100, 200, 150, 80, 300]
})
# Chain two query calls
result = (df
.query('year == 2023')
.query('revenue > 100')
.sort_values('revenue', ascending=False)
)
print(result)
# region year revenue
# 4 South 2023 300
# 2 North 2023 150query() 与布尔索引的比较
两种方法会产生相同的结果,但各有适用场景。对于使用布尔索引时需要许多括号的多条件筛选,query() 更具优势。当条件包含 query 字符串不支持的复杂 Python 表达式(例如方法调用)时,布尔索引更合适。
在大多数情况下,两者的性能相近;对于非常大的 DataFrame,query() 可能会稍快一些,因为它在底层使用了 numexpr 库。
import pandas as pd
df = pd.DataFrame({
'A': range(10),
'B': range(10, 20)
})
# Boolean indexing
result_bool = df[(df['A'] > 2) & (df['B'] < 18) & (df['A'] != 5)]
# Equivalent query — much more readable
result_query = df.query('A > 2 and B < 18 and A != 5')
print(result_query)
# A B
# 3 3 13
# 4 4 14
# 6 6 16
# 7 7 17query() 中的字符串比较
在查询字符串中,您可以通过给字符串字面量加引号来筛选字符串列的值。可以为外层查询字符串使用双引号、为字符串值使用单引号,也可以反过来使用,但请保持一致。请注意,query() 不支持 contains() 等 .str 方法;对于这类操作,请使用带有 .str 的布尔索引。
import pandas as pd
df = pd.DataFrame({
'country': ['USA', 'UK', 'Canada', 'USA', 'Germany'],
'sales': [400, 150, 200, 600, 300]
})
# Single quotes for the string value inside double-quoted query
result = df.query('country == "USA"')
print(result)
# country sales
# 0 USA 400
# 3 USA 600使用 in 和 not in 运算符
在查询字符串中,Pandas 支持使用 in 和 not in 运算符进行成员测试,类似于对 Python 列表进行测试。这是将多个 == 条件与 or 串联起来的一种简洁替代方式。值列表可以直接写在查询字符串中。
import pandas as pd
df = pd.DataFrame({
'status': ['active', 'inactive', 'pending', 'active', 'closed'],
'amount': [100, 200, 50, 300, 150]
})
# Keep rows where status is in a specific list
result = df.query('status in ["active", "pending"]')
print(result)
# status amount
# 0 active 100
# 2 pending 50
# 3 active 300
# Exclude certain statuses
excluded = df.query('status not in ["closed", "inactive"]')
print(excluded.shape) # (3, 2)使用 query() 筛选数值范围
Python 的链式比较(例如 10 < price < 500)可以在查询字符串中使用,因此范围筛选的表达能力很强。使用标准布尔索引时,必须使用 between(),或将两个独立条件与 & 组合,才能实现相同效果。
import pandas as pd
df = pd.DataFrame({
'product': ['A', 'B', 'C', 'D', 'E'],
'price': [5, 50, 150, 300, 500]
})
# Chained comparison — only works inside query()
result = df.query('50 <= price <= 300')
print(result)
# product price
# 1 B 50
# 2 C 150
# 3 D 300query() 的限制
query() 功能强大,但也有一些限制。包含空格或特殊字符的列名需要使用反引号。非常复杂的 Python 表达式(例如自定义函数和多行逻辑)不支持写在字符串中。此外,如果列名与 class 或 if 等 Python 关键字冲突,query() 可能会产生意外结果;这些列名同样需要使用反引号括起来。
对于 query() 无法清晰表达的条件,请改用标准布尔索引。
import pandas as pd
df = pd.DataFrame({'first name': ['Alice', 'Bob'], 'class': [1, 2]})
# Backtick-quote column names with spaces or reserved words
result = df.query('`first name` == "Alice" and `class` == 1')
print(result)
# first name class
# 0 Alice 1实践示例:筛选订单
下面是一个实践示例,演示如何将 query() 与变量引用结合起来,并串联到 groupby。先筛选、再聚合的这种模式可以避免处理不需要的行,因此在大型数据集上既更清晰,速度也更快。
import pandas as pd
orders = pd.DataFrame({
'region': ['East', 'West', 'East', 'West', 'East'],
'year': [2023, 2023, 2024, 2024, 2024],
'revenue': [100, 200, 300, 400, 500]
})
min_year = 2024
# Filter to recent orders in the East region, then sum revenue
summary = (
orders
.query('year >= @min_year and region == "East"')
.groupby('region')['revenue'].sum()
)
print(summary)
# region
# East 800
# Name: revenue, dtype: int64query() 与方法串联的最佳实践
在现代 Pandas 代码中,将 query() 放在方法串联中是一种最佳实践。它可以让数据转换流水线的每一步都清晰明了,并且能够自我说明。请将整个串联表达式放在括号中,这样就可以跨多行书写,而不需要使用反斜杠。
将 query() 与用于添加列的 assign()、用于聚合的 groupby() 以及用于自定义函数的 pipe() 结合起来,可以构建完全易读的流水线。
import pandas as pd
df = pd.DataFrame({
'dept': ['Eng', 'HR', 'Eng', 'Sales', 'HR'],
'salary': [90000, 50000, 120000, 70000, 55000],
'years': [3, 5, 8, 2, 4]
})
result = (
df
.query('years > 2 and dept != "HR"')
.assign(bonus=lambda x: x['salary'] * 0.1)
.sort_values('salary', ascending=False)
)
print(result[['dept', 'salary', 'bonus']])
# dept salary bonus
# 2 Eng 120000 12000.0
# 0 Eng 90000 9000.0快速检查
测试您对 query() 方法的理解。
课程回顾
在本课中,您学到了:query() 接受字符串形式的筛选表达式,使多条件筛选更易读;@variable_name 可以将 Python 变量注入查询;还可以使用标准布尔索引无法实现的 in/not in 和链式比较。接下来,我们将学习使用 isin() 和 between() 简洁地进行成员筛选和范围筛选。
常见问题解答
「query() 方法」课时是免费的吗?
是的 — 「query() 方法」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Pandas & NumPy Academy 课程的其余内容,请升级到 CoddyKit PRO。 Pandas & NumPy Academy 课程共包含 4 节课。
「query() 方法」这节课中我会学到什么?
使用 query() 将可读的筛选表达式写成字符串,借助 @ 在查询中使用 Python 变量,并串联多个筛选条件。 你通过在浏览器中直接运行的动手代码来练习 Pandas & NumPy Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Pandas & NumPy Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Pandas & NumPy Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「query() 方法」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Pandas & NumPy Academy 课中编写并运行代码吗?
能。每节 Pandas & NumPy Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。