Метод query()
Записывайте понятные выражения фильтрации в виде строк с помощью query(), используйте переменные Python внутри запросов через @ и объединяйте фильтры в цепочку
«Метод query()» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения 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 150Сравнение query() и логической индексации
Оба метода дают одинаковый результат, но каждый подходит для своих задач. query() особенно удобен для фильтров с несколькими условиями, которые при логической индексации потребовали бы множества скобок. Логическая индексация лучше, когда условие содержит сложные выражения Python, например вызовы методов, не поддерживаемые в строках запросов.
В большинстве случаев производительность схожа; query() может быть немного быстрее для очень больших DataFrames, поскольку использует библиотеку 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 17Сравнение строк в query()
Фильтровать значения строкового столбца внутри строки запроса можно, заключив строковый литерал в кавычки. Используйте двойные кавычки для внешней строки запроса и одинарные — для строкового значения или наоборот — главное, будьте последовательны. Обратите внимание: query() не поддерживает методы .str, такие как contains(); для них используйте булеву индексацию с .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 300Ограничения query()
query() — мощный инструмент, но у него есть несколько ограничений. Имена столбцов, содержащие пробелы или специальные символы, необходимо заключать в обратные кавычки. Очень сложные выражения Python (пользовательские функции, многострочная логика) нельзя использовать внутри строки. Кроме того, query() может давать неожиданные результаты, если имена столбцов совпадают с ключевыми словами Python, например class или if — такие имена тоже заключайте в обратные кавычки.
Если выразить условие с помощью 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<p>Рассмотрим практический пример, в котором query() используется вместе со ссылкой на переменную и последующей цепочкой вызова groupby. Такой подход — сначала отфильтровать, затем агрегировать — позволяет не обрабатывать ненужные строки, что делает код понятнее и ускоряет работу с большими наборами данных.</p>
Вот практическая демонстрация, в которой 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: int64Лучшие практики использования query() и цепочек методов
Использование query() внутри цепочки методов считается хорошей практикой в современном коде Pandas. Каждый шаг конвейера преобразований становится понятным и самодокументируемым. Заключайте всю цепочку в круглые скобки, чтобы переносить её на несколько строк без обратных косых черт.
Сочетайте 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()» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Чему я научусь в уроке «Метод query()»?
Записывайте понятные выражения фильтрации в виде строк с помощью query(), используйте переменные Python внутри запросов через @ и объединяйте фильтры в цепочку Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?
Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Метод query()»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?
Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.