Pandas DataFrame: Методы извлечения и фильтрации строк по значению столбца и сложным условиям

Pandas DataFrame является краеугольным камнем для работы с табличными данными в Python. Одной из наиболее частых и критически важных операций при анализе данных является извлечение или фильтрация строк, которые соответствуют определенным критериям. Будь то выбор записей по точному значению в столбце, фильтрация по диапазону числовых значений, поиск подстрок в текстовых полях или комбинирование нескольких сложных условий, эффективное владение этими методами значительно повышает производительность и точность анализа.

В этой статье мы подробно рассмотрим различные подходы и мощные инструменты, предоставляемые библиотекой Pandas, для выбора и фильтрации строк. Мы начнем с основ булевого индексирования и постепенно перейдем к более продвинутым техникам, таким как использование isin(), строковых методов (str.contains()), регулярных выражений, а также гибких методов loc[] и query(). Цель — предоставить исчерпывающее руководство, которое поможет вам уверенно манипулировать данными, извлекая именно те подмножества, которые необходимы для вашего анализа.

Основы извлечения строк с использованием булевых условий

Булево индексирование является краеугольным камнем для эффективного извлечения данных в Pandas. Оно позволяет выбирать строки DataFrame, передавая ему серию булевых значений (True/False), где True соответствует строкам, которые должны быть включены в результат, а False — исключены. Длина этой булевой серии должна совпадать с количеством строк в исходном DataFrame.

Самый простой способ применить булево индексирование — это извлечь строки по точному совпадению значения в определенном столбце. Например, чтобы выбрать все записи, где значение столбца 'Категория' равно 'Электроника', мы можем использовать выражение df['Категория'] == 'Электроника'. Это условие генерирует булеву серию, которую затем можно передать DataFrame:

import pandas as pd

data = {'Продукт': ['Ноутбук', 'Мышь', 'Клавиатура', 'Монитор'],
        'Категория': ['Электроника', 'Электроника', 'Периферия', 'Электроника'],
        'Цена': [1200, 25, 75, 300]}
df = pd.DataFrame(data)

# Извлечение строк, где 'Категория' точно равна 'Электроника'
электроника_df = df[df['Категория'] == 'Электроника']
print(электроника_df)

Этот подход является интуитивно понятным и высокопроизводительным для базовых операций фильтрации.

Что такое булево индексирование в Pandas?

Булево индексирование — это один из наиболее мощных и интуитивно понятных способов фильтрации данных в Pandas DataFrame. Его суть заключается в использовании булевой (логической) серии или массива, где каждый элемент соответствует строке в DataFrame. Если значение в булевой серии True, соответствующая строка включается в результат; если False, строка исключается.

Эта булева серия обычно создается путем применения логических условий к одному или нескольким столбцам DataFrame. Например, условие df['столбец'] == 'значение' возвращает булеву серию, указывающую, какие строки удовлетворяют этому условию. Затем эта серия передается в оператор квадратных скобок DataFrame (df[...]), чтобы выбрать только те строки, для которых условие истинно. Такой подход обеспечивает высокую гибкость и производительность при работе с большими наборами данных.

Извлечение строк по точному совпадению значения в столбце

Самый простой и часто используемый способ применения булевого индексирования — это извлечение строк, где значение в определенном столбце точно соответствует заданному критерию. Этот подход позволяет быстро выделить подмножество данных, удовлетворяющее конкретному условию.

Для выполнения такой фильтрации мы создаем булеву серию, сравнивая значения столбца с искомым значением. Затем эта серия используется для индексирования DataFrame.

Рассмотрим пример:

import pandas as pd

data = {
    'Продукт': ['Яблоко', 'Банан', 'Апельсин', 'Яблоко', 'Манго'],
    'Цена': [100, 50, 120, 110, 90],
    'Количество': [10, 25, 15, 8, 20]
}
df = pd.DataFrame(data)

# Извлечение строк, где 'Продукт' равен 'Яблоко'
apple_products = df[df['Продукт'] == 'Яблоко']
print(apple_products)

В этом примере df['Продукт'] == 'Яблоко' создает булеву серию [True, False, False, True, False]. Когда эта серия передается в df[...], Pandas возвращает только те строки, для которых соответствующее значение в булевой серии равно True.

Фильтрация по множественным значениям и диапазонам

Часто возникает необходимость выбрать строки, где значение столбца соответствует одному из нескольких возможных вариантов или находится в определенном диапазоне. Pandas предоставляет удобные инструменты для таких сценариев.

Выбор строк, где значение столбца находится в списке: метод isin()

Метод isin() позволяет эффективно фильтровать DataFrame, проверяя, содержится ли значение в столбце в заданном списке. Это значительно упрощает синтаксис по сравнению с использованием множества операторов | (OR).

import pandas as pd

data = {'Продукт': ['Яблоко', 'Банан', 'Апельсин', 'Груша', 'Манго'],
        'Цена': [10, 15, 12, 18, 25]}
df = pd.DataFrame(data)

# Выбор продуктов, цена которых находится в списке [10, 18, 25]
продукты_по_цене = df[df['Цена'].isin([10, 18, 25])]
print(продукты_по_цене)

Извлечение строк по диапазону значений и операторам сравнения (>, <, >=, <=)

Для фильтрации числовых или временных данных по диапазону используются стандартные операторы сравнения. Вы можете комбинировать их для создания сложных условий диапазона.

# Выбор продуктов, цена которых строго больше 10 и меньше или равна 18
продукты_в_диапазоне = df[(df['Цена'] > 10) & (df['Цена'] <= 18)]
print(продукты_в_диапазоне)

Эти методы позволяют гибко извлекать данные, основываясь на множественных дискретных значениях или непрерывных диапазонах.

Выбор строк, где значение столбца находится в списке: метод isin()

Когда требуется выбрать строки, где значение определенного столбца совпадает с одним из нескольких заданных значений, метод isin() становится незаменимым инструментом. Он позволяет эффективно проверять принадлежность каждого элемента столбца к списку или другой коллекции значений.

Синтаксис isin() прост: df[столбец].isin(список_значений). Этот метод возвращает булеву серию, которую затем можно использовать для индексирования DataFrame.

Рассмотрим пример. Допустим, у нас есть DataFrame с информацией о продуктах, и мы хотим выбрать только те, которые относятся к категориям ‘Электроника’ или ‘Одежда’:

import pandas as pd

data = {
    'Продукт': ['Ноутбук', 'Футболка', 'Мышь', 'Джинсы', 'Монитор'],
    'Категория': ['Электроника', 'Одежда', 'Электроника', 'Одежда', 'Электроника'],
    'Цена': [1200, 25, 30, 50, 300]
}
df = pd.DataFrame(data)

# Список категорий для фильтрации
желаемые_категории = ['Электроника', 'Одежда']

# Фильтрация с использованием isin()
df_filtered = df[df['Категория'].isin(желаемые_категории)]
print(df_filtered)

Этот подход значительно упрощает код по сравнению с использованием множественных операторов | (OR) для каждого значения.

Извлечение строк по диапазону значений и операторам сравнения (>, <, >=, <=)

Помимо фильтрации по дискретным значениям с помощью isin(), часто возникает необходимость выбрать строки, где значения в числовом столбце попадают в определенный диапазон или удовлетворяют условиям сравнения. Pandas позволяет легко это сделать, используя стандартные операторы сравнения:

  • > (больше)

  • < (меньше)

  • >= (больше или равно)

  • <= (меньше или равно)

  • == (равно)

  • != (не равно)

Эти операторы применяются непосредственно к сериям (столбцам DataFrame), возвращая булеву серию, которую затем можно использовать для индексирования DataFrame.

Пример:

Предположим, у нас есть DataFrame df с колонкой ‘Возраст’. Чтобы выбрать всех, кто старше 30 лет:

df_older_than_30 = df[df['Возраст'] > 30]

Для выбора строк, где ‘Возраст’ находится в диапазоне от 25 до 40 лет (включительно), можно объединить два условия с помощью логического оператора & (AND):

df_age_range = df[(df['Возраст'] >= 25) & (df['Возраст'] <= 40)]

Такой подход обеспечивает гибкость при работе с числовыми данными, позволяя точно определять границы выборки.

Работа со строковыми данными: поиск подстрок и шаблонов

Переходя от числовых диапазонов, рассмотрим методы фильтрации DataFrame, когда критерием выступают строковые значения. Pandas предоставляет мощные инструменты для поиска подстрок и соответствия шаблонам.

Фильтрация по частичному совпадению текста: str.contains(), str.startswith(), str.endswith()

Для выбора строк, где текстовый столбец содержит определенную подстроку, используется метод .str.contains(). Он возвращает булеву серию, которую можно применить для индексирования DataFrame. Например, df[df['столбец'].str.contains('подстрока', na=False)].

Аналогично, методы .str.startswith() и .str.endswith() позволяют фильтровать строки по началу или окончанию строкового значения в столбце. Эти методы также принимают параметр na=False для корректной обработки пропущенных значений.

Использование регулярных выражений для сложных строковых условий

Метод .str.contains() обладает дополнительной гибкостью, поддерживая регулярные выражения. Это позволяет создавать сложные шаблоны для поиска, например, df[df['столбец'].str.contains(r'^A.*Z$', regex=True, na=False)] найдет строки, начинающиеся с ‘A’ и заканчивающиеся на ‘Z’. Использование регулярных выражений значительно расширяет возможности фильтрации строковых данных.

Реклама

Фильтрация по частичному совпадению текста: str.contains(), str.startswith(), str.endswith()

Когда требуется найти строки, где текстовое значение столбца содержит определенную подстроку, начинается или заканчивается на заданный текст, Pandas предлагает удобные методы доступа к строковым данным через аксессор .str.

Метод str.contains() позволяет отфильтровать строки, если столбец содержит указанную подстроку. Он поддерживает аргумент case=False для игнорирования регистра:

# Выбор продуктов, содержащих "Dell"
df[df['Продукт'].str.contains('Dell')]

# Выбор продуктов, содержащих "logi" без учета регистра
df[df['Продукт'].str.contains('logi', case=False)]

Для проверки начала строки используйте str.startswith():

# Продукты, начинающиеся с "Ноутбук"
df[df['Продукт'].str.startswith('Ноутбук')]

Аналогично, str.endswith() проверяет окончание строки:

# Продукты, заканчивающиеся на "Sony"
df[df['Продукт'].str.endswith('Sony')]

Эти методы незаменимы для базовой фильтрации текстовых данных.

Использование регулярных выражений для сложных строковых условий

Когда простые методы, такие как str.contains(), str.startswith() или str.endswith(), оказываются недостаточными для поиска сложных текстовых паттернов, на помощь приходят регулярные выражения. Pandas позволяет использовать всю мощь регулярных выражений через методы доступа к строкам str, в частности, с помощью str.contains(). По умолчанию str.contains() уже интерпретирует паттерн как регулярное выражение, что делает его чрезвычайно гибким инструментом.

Пример:

Предположим, нам нужно найти все строки, где столбец ‘Описание’ содержит либо слово "акция", либо "скидка", но только если они написаны с большой буквы или находятся в начале слова.

import pandas as pd

data = {'ID': [1, 2, 3, 4, 5],
        'Описание': ['Новая акция!', 'Большая скидка сегодня', 'акция на товары', 'Без скидки', 'Скидка 10%']}
df = pd.DataFrame(data)

# Фильтрация с использованием регулярного выражения
# Ищем 'Акция' или 'Скидка' (с большой буквы) или 'акция'/'скидка' в начале слова
filtered_df = df[df['Описание'].str.contains(r'\b[Аа]кция|\b[Сс]кидка', regex=True)]
print(filtered_df)

В этом примере r'\b[Аа]кция|\b[Сс]кидка' ищет слова "Акция"/"акция" или "Скидка"/"скидка" как целые слова (\b). Флаг regex=True (который является значением по умолчанию) явно указывает на использование регулярных выражений.

Комбинирование условий и альтернативные подходы

После освоения фильтрации по одиночным условиям, реальные задачи часто требуют объединения нескольких критериев. Pandas позволяет это делать с помощью стандартных логических операторов:

  • & (AND): Возвращает True, если все условия истинны.

  • | (OR): Возвращает True, если хотя бы одно условие истинно.

  • ~ (NOT): Инвертирует булево условие.

Пример: df[(df['Возраст'] > 30) & (df['Город'] == 'Москва')]

Хотя булево индексирование через [] и .loc[] является мощным, для повышения читаемости сложных условий можно использовать метод .query(). Он позволяет формулировать условия в виде строкового выражения, что напоминает синтаксис SQL. Это особенно удобно, когда условия включают несколько столбцов или переменных.

Пример: df.query("Возраст > 30 and Город == 'Москва'")

Объединение нескольких условий фильтрации: операторы AND (&), OR (|), NOT (~)

Часто возникает необходимость фильтровать данные по нескольким критериям одновременно. Pandas позволяет легко комбинировать булевы условия, используя стандартные логические операторы: & (логическое И), | (логическое ИЛИ) и ~ (логическое НЕ).

Для выбора строк, удовлетворяющих всем условиям, используйте оператор &. Например, чтобы найти людей из Москвы и с возрастом более 30 лет:

df[(df['Город'] == 'Москва') & (df['Возраст'] > 30)]

Если необходимо выбрать строки, удовлетворяющие хотя бы одному из условий, применяется оператор |. Например, люди из Москвы или с доходом более 80000:

df[(df['Город'] == 'Москва') | (df['Доход'] > 80000)]

Оператор ~ инвертирует булево условие, позволяя исключить строки. Например, все, кроме жителей Москвы:

df[~(df['Город'] == 'Москва')]

Важно заключать каждое отдельное условие в скобки, чтобы избежать ошибок из-за приоритета операторов.

Гибкая фильтрация с использованием методов .loc[] и .query()

Метод .loc[] является основным инструментом для выбора строк и столбцов по меткам, но он также исключительно эффективен для фильтрации с использованием булевых массивов. Вы можете передать ему булеву серию, полученную из одного или нескольких комбинированных условий, чтобы извлечь соответствующие строки. Это обеспечивает явный и мощный способ фильтрации:

df_filtered_loc = df.loc[(df['Возраст'] > 30) & (df['Город'] == 'Нью-Йорк')]

Альтернативой, предлагающей более читабельный синтаксис, особенно для сложных условий, является метод .query(). Он позволяет фильтровать DataFrame, используя строковое выражение, напоминающее SQL-запрос. Это может значительно улучшить читаемость кода, избегая повторения имени DataFrame:

df_filtered_query = df.query('Возраст > 30 and Город == "Нью-Йорк"')

.query() автоматически обрабатывает имена столбцов, позволяя писать условия более естественно. Оба метода предоставляют гибкие и мощные средства для применения сложных условий фильтрации, но .query() часто предпочтительнее для интерактивного анализа из-за своей лаконичности.

Расширенные сценарии и обработка данных

После освоения гибких методов .loc[] и .query(), рассмотрим обработку особых случаев, таких как пропущенные значения, и эффективное исключение данных.

Обработка пропущенных значений (NaN) при фильтрации строк Пропущенные значения (NaN) могут влиять на результаты фильтрации. Pandas предоставляет методы для их обнаружения:

  • df['Столбец'].isna(): Возвращает True для NaN.

  • df['Столбец'].notna(): Возвращает True для не-NaN. Пример: df[df['Возраст'].isna()] выберет строки с отсутствующим возрастом.

Исключение строк по заданным значениям или условиям Для исключения строк, соответствующих определенным критериям, используйте оператор логического отрицания ~ (тильда) перед булевым условием. Пример:

  • df[~ (df['Категория'] == 'Устаревшее')] исключит строки с категорией ‘Устаревшее’.

  • df[~ df['ID'].isin([101, 105])] исключит строки с указанными ID. Этот подход позволяет инвертировать любое условие фильтрации.

Обработка пропущенных значений (NaN) при фильтрации строк

При работе с реальными данными пропущенные значения (NaN) встречаются часто и могут существенно влиять на результаты фильтрации. По умолчанию, при использовании булевых условий, строки с NaN в проверяемом столбце обычно исключаются из результата, так как сравнения с NaN (например, NaN == 5 или NaN > 0) всегда возвращают False или NaN, которые интерпретируются как False.

Для явного включения или исключения строк с NaN используйте методы isna() и notna():

  • df['столбец'].isna(): Возвращает булеву серию, где True указывает на пропущенное значение в соответствующей строке. Это позволяет выбрать все строки, где в указанном столбце есть NaN.

  • df['столбец'].notna(): Возвращает булеву серию, где True указывает на не пропущенное значение. Используется для выбора всех строк, где в столбце присутствует валидное значение.

Эти методы можно комбинировать с другими условиями фильтрации, чтобы точно контролировать обработку пропущенных значений в вашем DataFrame.

Исключение строк по заданным значениям или условиям

После того как мы разобрались с пропущенными значениями, часто возникает необходимость исключить строки, которые содержат определенные, но нежелательные значения или не соответствуют заданным критериям. Это обратная операция фильтрации, где мы явно удаляем данные, а не выбираем их. Для исключения строк по заданным значениям можно использовать оператор инверсии ~ в сочетании с методом isin():

import pandas as pd
data = {'ID': [1, 2, 3, 4, 5], 'Category': ['A', 'B', 'C', 'A', 'B'], 'Value': [10, 20, 30, 40, 50]}
df = pd.DataFrame(data)
# Исключаем строки, где 'Category' равно 'A' или 'C'
df_excluded_categories = df[~df['Category'].isin(['A', 'C'])]
print(df_excluded_categories)

Аналогично, для исключения строк по более сложным условиям, оператор ~ применяется к булевой серии, полученной из условия:

# Исключаем строки, где 'Value' больше 30
df_excluded_values = df[~(df['Value'] > 30)]
print(df_excluded_values)

Такой подход обеспечивает гибкость при очистке и подготовке данных, позволяя легко удалять нерелевантные записи.

Заключение

В этом всеобъемлющем руководстве мы подробно рассмотрели многообразие методов извлечения и фильтрации строк в Pandas DataFrame. От базового булева индексирования и точного совпадения значений до работы со списками, диапазонами, сложными строковыми шаблонами и регулярными выражениями – Pandas предоставляет мощный арсенал инструментов. Мы также изучили, как эффективно комбинировать условия с помощью логических операторов, использовать гибкие методы .loc[] и .query(), а также обрабатывать пропущенные значения и исключать ненужные строки.

Освоение этих техник является краеугольным камнем для любого специалиста по данным, работающего с Pandas. Они позволяют не только быстро получать необходимые подмножества данных для анализа, но и значительно повышают эффективность и чистоту вашего кода. Применяя эти знания на практике, вы сможете уверенно манипулировать данными, извлекая из них максимальную ценность.


Добавить комментарий