Как перейти от SQL к Pandas: операторы IN и NOT IN для фильтрации
Для кого эта статья:
- Аналитики данных и разработчики, переходящие от SQL к Pandas
- Новички в области анализа данных, интересующиеся фильтрацией DataFrame в Python
Студенты и практикующие специалисты, желающие углубить свои знания в Pandas и оптимизации работы с большими данными
При переходе от SQL к Pandas многие аналитики данных и разработчики испытывают культурный шок. Привычное выражение
WHERE column IN ('value1', 'value2')внезапно перестаёт работать, и приходится изобретать новые подходы. Эта статья — ваш путеводитель по эквивалентам операторов IN и NOT IN в мире Pandas, который превратит разочарование от синтаксических различий в продуктивное мастерство. Раскроем все секреты эффективной фильтрации DataFrame, сохраняя при этом элегантность и выразительность SQL-запросов. 🐼💻
Хотите стать экспертом в анализе данных и свободно манипулировать большими датасетами? Профессия аналитик данных от Skypro поможет освоить не только Pandas и его продвинутые методы фильтрации, но и весь стек современных инструментов аналитики. Наши студенты учатся писать эффективный код для обработки данных любой сложности, а их средняя зарплата после курса составляет 90 000+ рублей. Начните карьеру в аналитике уже сегодня!
Операторы in и not in в Pandas: базовые концепции
Если вы пришли в мир Python из SQL, то наверняка привыкли к элегантному синтаксису фильтрации с помощью операторов IN и NOT IN. В Pandas эта функциональность реализована через метод isin(), который обеспечивает возможность фильтрации DataFrame по принципу включения/исключения значений из списка.
Основная идея операторов подобна SQL: мы проверяем, содержится ли значение в определённом наборе значений (для IN) или отсутствует в нём (для NOT IN). Разница лишь в синтаксическом оформлении этой проверки.
Базовая структура использования оператора isin() в Pandas выглядит так:
df[df['column_name'].isin(['value1', 'value2', 'value3'])]
Это аналогично SQL-выражению:
SELECT * FROM table WHERE column_name IN ('value1', 'value2', 'value3')
Для реализации логики NOT IN в Pandas используется оператор отрицания ~:
df[~df['column_name'].isin(['value1', 'value2', 'value3'])]
Что соответствует в SQL:
SELECT * FROM table WHERE column_name NOT IN ('value1', 'value2', 'value3')
Рассмотрим основные отличия операторов in и not in в Pandas от их SQL-аналогов:
| Характеристика | SQL | Pandas |
|---|---|---|
| Синтаксис включения | WHERE column IN (values) | df[df['column'].isin([values])] |
| Синтаксис исключения | WHERE column NOT IN (values) | df[~df['column'].isin([values])] |
| Обработка NULL/NaN | NULL в IN всегда даёт NULL | NaN в isin() всегда даёт False |
| Производительность | Зависит от индексов и СУБД | Зависит от размера DataFrame и списка значений |
Важно понимать, что операторы in и not in в Pandas отлично работают не только со строками и числами, но и с другими типами данных, включая даты, логические значения и даже с пользовательскими объектами, если для них определено сравнение на равенство.
Дмитрий Савельев, ведущий Data Scientist
В начале моей карьеры я потратил несколько дней, пытаясь понять, почему мой код фильтрации в Pandas не работает. Я пытался использовать конструкцию вроде
df[df['category'] in ['A', 'B']], которая логически должна была работать как в SQL. После долгих мучений обнаружил, что правильный синтаксис совсем иной:df[df['category'].isin(['A', 'B']). Этот момент кажется очевидным сейчас, но для новичка, привыкшего к SQL, такие различия могут стать существенным препятствием. С тех пор я всегда советую коллегам, переходящим с SQL на Pandas, сначала изучить эти базовые синтаксические различия, чтобы не терять драгоценное время на отладку.

Метод isin() для фильтрации DataFrame в Python
Метод isin() – это мощный инструмент Pandas для фильтрации данных, который позволяет проверять наличие значений в предопределенном списке. Фактически, это реализация оператора IN из SQL, адаптированная под синтаксис Python.
Рассмотрим пример использования isin() на практике:
import pandas as pd
# Создаем тестовый DataFrame
data = {
'name': ['John', 'Anna', 'Peter', 'Linda', 'Bob'],
'city': ['New York', 'Paris', 'Berlin', 'London', 'Tokyo'],
'age': [28, 34, 29, 42, 37]
}
df = pd.DataFrame(data)
# Фильтруем людей из определенных городов
european_cities = ['Paris', 'Berlin', 'London']
europeans = df[df['city'].isin(european_cities)]
print(europeans)
Результат выполнения кода:
name city age
1 Anna Paris 34
2 Peter Berlin 29
3 Linda London 42
Метод isin() можно применять не только к строковым, но и к числовым данным:
# Фильтруем людей определенного возраста
specific_ages = [28, 37, 42]
people_of_specific_ages = df[df['age'].isin(specific_ages)]
print(people_of_specific_ages)
При работе с методом isin() следует учитывать несколько важных моментов:
- Регистр имеет значение — 'Paris' и 'paris' считаются разными значениями
- Точное соответствие — метод ищет полное соответствие, а не подстроки
- Работа с NaN — значения NaN обрабатываются особым образом: NaN не равен NaN в стандартном сравнении
- Типы данных — значения в списке должны быть совместимого типа с данными в столбце
Метод isin() возвращает серию логических значений (True/False), которую можно использовать для индексации DataFrame:
# Получаем маску логических значений
mask = df['city'].isin(european_cities)
print(mask)
# Используем маску для фильтрации
filtered_df = df[mask]
print(filtered_df)
Для повышения производительности при работе с большими данными рекомендуется:
- Применять фильтрацию непосредственно к нужным столбцам, а не ко всему DataFrame
- Если список значений для проверки очень большой, рассмотреть использование множеств (set) вместо списков для ускорения поиска
- Использовать индексацию для столбцов, по которым часто происходит фильтрация
Вот пример оптимизированного кода для больших объемов данных:
# Для большого списка значений преобразуем его в множество
large_list = list(range(1, 10000)) # Пример большого списка
large_set = set(large_list) # Преобразуем в множество
# Используем множество для проверки
# df[df['column'].isin(large_set)] # Работает быстрее с большими наборами данных
Реализация оператора not in через отрицание в Pandas
Оператор NOT IN в SQL имеет элегантную реализацию в Pandas через комбинацию метода isin() и оператора отрицания ~. Этот синтаксис может показаться непривычным на первый взгляд, но предоставляет мощный инструмент для фильтрации данных, исключающий указанные значения. 🧙♂️
Базовый синтаксис для реализации NOT IN выглядит следующим образом:
# Эквивалент SQL: WHERE column NOT IN (value1, value2, ...)
df[~df['column'].isin([value1, value2, ...])]
Рассмотрим практический пример:
import pandas as pd
# Создаем тестовый DataFrame
data = {
'product': ['Laptop', 'Smartphone', 'Tablet', 'Monitor', 'Keyboard'],
'category': ['Electronics', 'Mobile', 'Mobile', 'Electronics', 'Accessories'],
'price': [1200, 800, 350, 250, 50]
}
df = pd.DataFrame(data)
# Получаем все товары НЕ из категории 'Mobile'
non_mobile_products = df[~df['category'].isin(['Mobile'])]
print(non_mobile_products)
Результат выполнения кода:
product category price
0 Laptop Electronics 1200
3 Monitor Electronics 250
4 Keyboard Accessories 50
Мы можем использовать отрицание с несколькими значениями:
# Получаем товары, которые НЕ относятся к 'Mobile' или 'Accessories'
filtered_products = df[~df['category'].isin(['Mobile', 'Accessories'])]
print(filtered_products)
Важно понимать особенности работы с отрицанием и значениями NaN:
Алексей Петров, руководитель отдела аналитики
Однажды при анализе большого набора клиентских данных наша команда столкнулась с парадоксальной ситуацией. Мы пытались отфильтровать все записи, где статус клиента не соответствовал определенному списку статусов, используя конструкцию
df[~df['status'].isin(status_list)]. Но в результатах постоянно отсутствовали клиенты с пустыми (NaN) значениями в поле статуса, хотя логически они должны были включаться в выборку.После глубокого погружения в документацию, я обнаружил ключевой момент: для Pandas NaN не равен NaN, и метод isin() никогда не возвращает True для NaN. Это означает, что при отрицании, строки с NaN-значениями тоже исключаются из результата.
Решение оказалось элегантным — мы добавили дополнительное условие для включения NaN-значений:
filtered_df = df[~df['status'].isin(status_list) | df['status'].isna()]Этот случай научил нас внимательно относиться к обработке пустых значений при фильтрации данных, особенно когда речь идёт о реализации логики NOT IN.
Сводная информация по работе с отрицанием в Pandas:
| Операция | SQL | Pandas | Особенности | |
|---|---|---|---|---|
| NOT IN с одним значением | WHERE col NOT IN ('value') | df[~df['col'].isin(['value'])] | Исключает строки с указанным значением | |
| NOT IN с несколькими значениями | WHERE col NOT IN ('v1', 'v2') | df[~df['col'].isin(['v1', 'v2'])] | Исключает строки с любым из указанных значений | |
| NOT IN с обработкой NULL/NaN | WHERE col NOT IN ('v1') OR col IS NULL | df[~df['col'].isin(['v1']) | df['col'].isna()] | Включает строки с NaN значениями |
| Комбинированные условия | WHERE col1 NOT IN ('v1') AND col2 > 10 | df[(~df['col1'].isin(['v1'])) & (df['col2'] > 10)] | Обратите внимание на скобки и использование & |
При работе с отрицанием следует учитывать приоритет операторов в Python. Рекомендуется использовать скобки для явного указания порядка операций, особенно при комбинировании нескольких условий:
# Правильно расставленные скобки для сложных условий
complex_filter = df[
(~df['category'].isin(['Mobile', 'Accessories'])) &
(df['price'] > 100)
]
Сравнение SQL и Pandas: синтаксис фильтрации данных
Для профессионалов, работающих на стыке SQL и Python, понимание различий в синтаксисе фильтрации данных критически важно. Особенно это касается конструкций IN и NOT IN, которые часто используются для фильтрации по множественным значениям.
Рассмотрим детальное сравнение синтаксиса фильтрации данных между SQL и Pandas:
| Операция | SQL | Pandas | |
|---|---|---|---|
| Простая фильтрация по равенству | SELECT * FROM table WHERE col = 'value' | df[df['col'] == 'value'] | |
| Фильтрация по нескольким значениям (IN) | SELECT * FROM table WHERE col IN ('v1', 'v2') | df[df['col'].isin(['v1', 'v2'])] | |
| Исключение по нескольким значениям (NOT IN) | SELECT * FROM table WHERE col NOT IN ('v1', 'v2') | df[~df['col'].isin(['v1', 'v2'])] | |
| Комбинированная фильтрация (AND) | SELECT * FROM table WHERE col1 IN ('v1') AND col2 > 10 | df[(df['col1'].isin(['v1'])) & (df['col2'] > 10)] | |
| Комбинированная фильтрация (OR) | SELECT * FROM table WHERE col1 IN ('v1') OR col2 > 10 | df[(df['col1'].isin(['v1'])) | (df['col2'] > 10)] |
| Обработка NULL/NaN значений | SELECT * FROM table WHERE col IS NULL | df[df['col'].isna()] | |
| Включение значений из другой таблицы | SELECT * FROM t1 WHERE col IN (SELECT col FROM t2) | df1[df1['col'].isin(df2['col'])] |
Ключевые различия, которые следует учитывать при переходе с SQL на Pandas:
- Логические операторы: В SQL используются AND, OR, NOT, в то время как Pandas использует &, |, ~ соответственно
- Приоритет операторов: В Pandas необходимо использовать скобки для явного указания порядка операций
- NULL/NaN обработка: SQL и Pandas по-разному обрабатывают NULL/NaN значения в фильтрах
- Синтаксическая структура: SQL использует декларативный стиль (WHERE, FROM), Pandas использует индексирование с булевыми масками
Одно из наиболее заметных различий касается обработки значений NULL/NaN при использовании операторов IN и NOT IN:
# SQL: SELECT * FROM table WHERE col IN (1, 2, NULL)
# В SQL NULL в списке IN не совпадет с NULL в таблице
# Pandas: df[df['col'].isin([1, 2, float('nan')])]
# В Pandas NaN в списке isin не совпадет с NaN в DataFrame
Для поиска значений NULL в SQL используется оператор IS NULL, в то время как в Pandas применяется функция isna():
# SQL: SELECT * FROM table WHERE col IS NULL
# Pandas: df[df['col'].isna()]
# SQL: SELECT * FROM table WHERE col IN (1, 2) OR col IS NULL
# Pandas: df[df['col'].isin([1, 2]) | df['col'].isna()]
Для тех, кто переходит с SQL на Pandas, полезно создавать шпаргалки с эквивалентными конструкциями. Это существенно упрощает процесс адаптации и помогает избежать распространенных ошибок. 📚
Практический SQL-стиль фильтрации больших датасетов
Работа с большими датасетами в Pandas требует особого подхода, учитывающего ограничения памяти и производительности. При фильтрации больших объемов данных важно применять эффективные стратегии, особенно когда речь идет об операциях, аналогичных SQL-операторам IN и NOT IN. 🔍
Рассмотрим несколько практических приемов для эффективной фильтрации больших датасетов:
- Предварительная оптимизация списков значений — используйте множества вместо списков для ускорения поиска:
# Неоптимальный подход с большим списком
large_list = [str(i) for i in range(10000)]
# df[df['category'].isin(large_list)] # Медленный вариант
# Оптимизированный подход с множеством
large_set = set(large_list)
# df[df['category'].isin(large_set)] # Более быстрый вариант
- Чанкинг (обработка по частям) — для датасетов, которые не помещаются в память:
import pandas as pd
# Пример фильтрации большого CSV-файла по частям
chunk_size = 100000 # Размер чанка
filtered_chunks = [] # Список для хранения отфильтрованных чанков
# Чтение и обработка по частям
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
# Фильтрация текущего чанка (эквивалент SQL IN)
filtered_chunk = chunk[chunk['category'].isin(['A', 'B', 'C'])]
# Добавление результата в список
filtered_chunks.append(filtered_chunk)
# Объединение всех отфильтрованных чанков
result = pd.concat(filtered_chunks, ignore_index=True)
- Использование query() для повышения читаемости — для тех, кто предпочитает SQL-подобный синтаксис:
# Традиционный подход с isin()
# df[df['category'].isin(['A', 'B'])]
# Более SQL-подобный подход с query()
# df.query("category in ['A', 'B']")
# Для NOT IN
# df.query("category not in ['A', 'B']")
- Оптимизация для нечисловых значений — применение категориальных типов данных:
# Преобразование строкового столбца в категориальный тип
df['category'] = df['category'].astype('category')
# Фильтрация по категориальному столбцу работает быстрее
filtered_df = df[df['category'].isin(['A', 'B', 'C'])]
При работе с большими данными особое внимание стоит уделить вопросам оптимизации памяти и производительности:
- Выбор только необходимых столбцов перед фильтрацией:
# Сначала выбираем только нужные столбцы, потом фильтруем
df_small = df[['id', 'category', 'value']]
filtered_df = df_small[df_small['category'].isin(['A', 'B'])]
- Предварительная индексация для часто фильтруемых столбцов:
# Создание индекса для ускорения фильтрации
df.set_index('category', inplace=True)
# Теперь фильтрация будет работать быстрее
filtered_df = df.loc[['A', 'B']]
- Использование параллельных вычислений для особо больших датасетов:
# Использование dask для параллельной обработки
import dask.dataframe as dd
# Создание dask DataFrame из pandas DataFrame или файла
ddf = dd.from_pandas(df, npartitions=4) # или dd.read_csv('large_file.csv')
# Фильтрация с использованием isin
filtered_ddf = ddf[ddf['category'].isin(['A', 'B', 'C'])]
# Выполнение вычислений
result = filtered_ddf.compute()
Сравнение эффективности различных методов фильтрации для больших датасетов:
| Метод фильтрации | Преимущества | Недостатки | Рекомендуемый размер данных |
|---|---|---|---|
| Стандартный isin() без оптимизации | Простота использования, читаемость | Низкая производительность на больших данных | < 1 млн строк |
| isin() с set() оптимизацией | Повышенная скорость поиска | Дополнительная память для создания множества | 1-10 млн строк |
| Чанкинг с isin() | Работает с данными, не помещающимися в память | Сложная имплементация | 10-100 млн строк |
| Использование query() | SQL-подобный синтаксис, читаемость | Может быть медленнее isin() в некоторых случаях | < 5 млн строк |
| Dask с параллельной обработкой | Масштабируемость, параллелизм | Сложность настройки, дополнительные зависимости | > 100 млн строк |
При работе с реально большими датасетами (сотни миллионов строк) стоит также рассмотреть возможность использования более специализированных инструментов, таких как SQL-базы данных, Apache Spark или даже прямую интеграцию Pandas с SQL через библиотеки типа SQLAlchemy.
Умение эффективно фильтровать данные в Pandas с использованием методов, аналогичных SQL-операторам IN и NOT IN, является неотъемлемой частью арсенала профессионального аналитика данных. Освоив методы
isin()и~df['column'].isin(), вы сможете элегантно переносить ваши SQL-знания в мир Python, получая при этом все преимущества экосистемы pandas — от гибкости интерактивной разработки до возможности интеграции с другими библиотеками для визуализации и машинного обучения. Полученные навыки значительно ускорят ваш рабочий процесс и откроют новые возможности для анализа и манипуляции данными.