Как перейти от SQL к Pandas: операторы IN и NOT IN для фильтрации

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Аналитики данных и разработчики, переходящие от 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() на практике:

Python
Скопировать код
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() можно применять не только к строковым, но и к числовым данным:

Python
Скопировать код
# Фильтруем людей определенного возраста
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:

Python
Скопировать код
# Получаем маску логических значений
mask = df['city'].isin(european_cities)
print(mask)

# Используем маску для фильтрации
filtered_df = df[mask]
print(filtered_df)

Для повышения производительности при работе с большими данными рекомендуется:

  1. Применять фильтрацию непосредственно к нужным столбцам, а не ко всему DataFrame
  2. Если список значений для проверки очень большой, рассмотреть использование множеств (set) вместо списков для ускорения поиска
  3. Использовать индексацию для столбцов, по которым часто происходит фильтрация

Вот пример оптимизированного кода для больших объемов данных:

Python
Скопировать код
# Для большого списка значений преобразуем его в множество
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 выглядит следующим образом:

Python
Скопировать код
# Эквивалент SQL: WHERE column NOT IN (value1, value2, ...)
df[~df['column'].isin([value1, value2, ...])]

Рассмотрим практический пример:

Python
Скопировать код
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

Мы можем использовать отрицание с несколькими значениями:

Python
Скопировать код
# Получаем товары, которые НЕ относятся к '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. Рекомендуется использовать скобки для явного указания порядка операций, особенно при комбинировании нескольких условий:

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
Скопировать код
# 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
Скопировать код
# 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. 🔍

Рассмотрим несколько практических приемов для эффективной фильтрации больших датасетов:

  1. Предварительная оптимизация списков значений — используйте множества вместо списков для ускорения поиска:
Python
Скопировать код
# Неоптимальный подход с большим списком
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)] # Более быстрый вариант

  1. Чанкинг (обработка по частям) — для датасетов, которые не помещаются в память:
Python
Скопировать код
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)

  1. Использование query() для повышения читаемости — для тех, кто предпочитает SQL-подобный синтаксис:
Python
Скопировать код
# Традиционный подход с isin()
# df[df['category'].isin(['A', 'B'])]

# Более SQL-подобный подход с query()
# df.query("category in ['A', 'B']")

# Для NOT IN
# df.query("category not in ['A', 'B']")

  1. Оптимизация для нечисловых значений — применение категориальных типов данных:
Python
Скопировать код
# Преобразование строкового столбца в категориальный тип
df['category'] = df['category'].astype('category')

# Фильтрация по категориальному столбцу работает быстрее
filtered_df = df[df['category'].isin(['A', 'B', 'C'])]

При работе с большими данными особое внимание стоит уделить вопросам оптимизации памяти и производительности:

  • Выбор только необходимых столбцов перед фильтрацией:
Python
Скопировать код
# Сначала выбираем только нужные столбцы, потом фильтруем
df_small = df[['id', 'category', 'value']]
filtered_df = df_small[df_small['category'].isin(['A', 'B'])]

  • Предварительная индексация для часто фильтруемых столбцов:
Python
Скопировать код
# Создание индекса для ускорения фильтрации
df.set_index('category', inplace=True)
# Теперь фильтрация будет работать быстрее
filtered_df = df.loc[['A', 'B']]

  • Использование параллельных вычислений для особо больших датасетов:
Python
Скопировать код
# Использование 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 — от гибкости интерактивной разработки до возможности интеграции с другими библиотеками для визуализации и машинного обучения. Полученные навыки значительно ускорят ваш рабочий процесс и откроют новые возможности для анализа и манипуляции данными.

Загрузка...