Фильтрация данных по условию

Фильтрация данных по условию Pandas

Привет! Ты уже умеешь загружать данные и выбирать колонки. Но часто нужно отобрать только те строки, которые соответствуют определённому условию. Хочешь найти всех клиентов старше 25 лет? Или все заказы за последний месяц? Для этого нужна фильтрация!

В этой статье мы разберём:

  • Булева индексация — самый простой способ фильтрации
  • Комбинирование условий: & и |
  • Метод query() для читаемых запросов
  • Фильтрация по списку значений с isin()
  • Поиск подстрок в тексте: str.contains()
  • Фильтрация по датам

Что нужно знать перед началом

Для этого урока тебе понадобится:

  • Установленный Pandas (pip install pandas)
  • Базовое понимание DataFrame и колонок
  • Знание операторов сравнения (><==!=)

Совет: Фильтрация — один из самых частых приёмов при работе с данными. Освоив его, ты сможешь быстро извлекать нужную информацию из больших таблиц.

Основная часть

Подготовка данных

Создадим DataFrame для примеров:

import pandas as pd
import numpy as np

np.random.seed(42)

data = {
    'Имя': ['Анна', 'Иван', 'Мария', 'Пётр', 'Ольга', 'Сергей', 'Елена', 'Дмитрий'],
    'Возраст': [25, 30, 22, 35, 28, 40, 33, 27],
    'Город': ['Москва', 'СПб', 'Казань', 'Новосибирск', 'Екатеринбург', 'Москва', 'СПб', 'Казань'],
    'Зарплата': [50000, 60000, 45000, 70000, 55000, 80000, 62000, 48000],
    'Оценка': [4.5, 3.8, 4.2, 4.0, 4.8, 3.9, 4.7, 4.1]
}

df = pd.DataFrame(data)
print("Наши данные:")
print(df)

Булева индексация: df[условие]

Самый простой способ отфильтровать строки:

# Выбираем строки, где возраст больше 30
filtered = df[df['Возраст'] > 30]
print(filtered)

Результат:

     Имя  Возраст         Город  Зарплата  Оценка
3   Пётр       35  Новосибирск     70000     4.0
5 Сергей       40        Москва     80000     3.9
6  Елена       33           СПб     62000     4.7

Совет: Условие df['Возраст'] > 30 создаёт булев массив [False, False, False, True, False, True, True, False]. DataFrame df[...] оставляет только те строки, где True.

Одно условие

Равенство

# Только из Москвы
moscow = df[df['Город'] == 'Москва']
print(moscow)

Не равно

# Не из Москвы
not_moscow = df[df['Город'] != 'Москва']
print(not_moscow)

Больше, меньше

# Зарплата >= 60000
high_salary = df[df['Зарплата'] >= 60000]
print(high_salary)

Несколько условий: & (И) и | (ИЛИ)

Для комбинирования условий используй & (И) и | (ИЛИ). Каждое условие оборачивай в скобки!

AND (оба условия)

# Возраст > 25 И Зарплата > 55000
filtered = df[(df['Возраст'] > 25) & (df['Зарплата'] > 55000)]
print(filtered)

Результат:

     Имя  Возраст Город  Зарплата  Оценка
1   Иван       30   СПб     60000     3.8
5 Сергей       40 Москва     80000     3.9
6  Елена       33   СПб     62000     4.7

OR (хотя бы одно условие)

# Возраст > 35 ИЛИ Зарплата > 70000
filtered = df[(df['Возраст'] > 35) | (df['Зарплата'] > 70000)]
print(filtered)

Результат:

     Имя  Возраст         Город  Зарплата  Оценка
3   Пётр       35  Новосибирск     70000     4.0
5 Сергей       40        Москва     80000     3.9

NOT (отрицание)

# Не из Москвы и не из СПб
filtered = df[~(df['Город'] == 'Москва') & ~(df['Город'] == 'СПб')]
print(filtered)

Результат:

     Имя  Возраст         Город  Зарплата  Оценка
2  Мария       22        Казань     45000     4.2
3   Пётр       35  Новосибирск     70000     4.0
4  Ольга       28  Екатеринбург     55000     4.8
7 Дмитрий       27        Казань     48000     4.1

Совет: Скобки вокруг каждого условия обязательны! Без них Python может неправильно расставить приоритеты.

Метод query() — читаемые запросы

query() позволяет писать условия в виде строки — очень читаемо:

# Возраст > 25 и Зарплата > 55000
filtered = df.query('Возраст > 25 and Зарплата > 55000')
print(filtered)

# Или с переменными
age_threshold = 25
salary_threshold = 55000
filtered = df.query('Возраст > @age_threshold and Зарплата > @salary_threshold')
print(filtered)

Совет: query() особенно удобен для сложных условий с несколькими переменными. Используй @имя_переменной для подстановки значений.

Фильтрация по списку: isin()

isin() проверяет, входит ли значение в заданный список:

# Только из Москвы или СПб
cities = ['Москва', 'СПб']
filtered = df[df['Город'].isin(cities)]
print(filtered)
# Все, кто НЕ из Москвы и СПб
filtered = df[~df['Город'].isin(cities)]
print(filtered)

Совет: isin() работает быстрее, чем несколько условий через |, особенно для длинных списков.

Поиск подстрок: str.contains()

Для фильтрации по части текста используй str.contains():

# Имена, начинающиеся с "А"
filtered = df[df['Имя'].str.contains('^А', na=False)]
print(filtered)

Результат:

   Имя  Возраст  Город  Зарплата  Оценка
0 Анна       25 Москва     50000     4.5
# Имена, содержащие "е"
filtered = df[df['Имя'].str.contains('е', na=False)]
print(filtered)

Результат:

      Имя  Возраст         Город  Зарплата  Оценка
2   Мария       22        Казань     45000     4.2
5  Сергей       40        Москва     80000     3.9
6   Елена       33           СПб     62000     4.7
7 Дмитрий       27        Казань     48000     4.1

Совет: na=False игнорирует пропуски. Если их не игнорировать — получишь ошибку.

Фильтрация по датам

import pandas as pd

# Создаём данные с датами
data = {
    'Дата': pd.date_range('2024-01-01', periods=10, freq='D'),
    'Продажи': np.random.randint(100, 300, 10)
}
df = pd.DataFrame(data)

# Фильтруем по дате
start_date = '2024-01-03'
end_date = '2024-01-07'
filtered = df[(df['Дата'] >= start_date) & (df['Дата'] <= end_date)]
print(filtered)
# Фильтруем по месяцу (с помощью dt)
filtered = df[df['Дата'].dt.month == 1]
print(filtered)

Фильтрация с несколькими условиями: практический пример

# Создаём более сложные данные
np.random.seed(42)
data = {
    'Товар': ['Ноутбук', 'Телефон', 'Планшет', 'Ноутбук', 'Телефон', 'Планшет'] * 3,
    'Продажи': np.random.randint(1, 20, 18),
    'Цена': [50000, 30000, 15000] * 6,
    'Город': ['Москва'] * 6 + ['СПб'] * 6 + ['Казань'] * 6
}
df = pd.DataFrame(data)
df['Выручка'] = df['Продажи'] * df['Цена']

print("Данные о продажах:")
print(df.head(10))

# 1. Товары с продажами > 10 в Москве
filtered = df[(df['Продажи'] > 10) & (df['Город'] == 'Москва')]
print("\n1. Товары с продажами > 10 в Москве:")
print(filtered[['Товар', 'Продажи', 'Город']])

# 2. Ноутбуки в любом городе с выручкой > 200000
filtered = df[(df['Товар'] == 'Ноутбук') & (df['Выручка'] > 200000)]
print("\n2. Ноутбуки с выручкой > 200 000:")
print(filtered[['Товар', 'Продажи', 'Город', 'Выручка']])

# 3. Товары в Казани ИЛИ продажи < 3
filtered = df[(df['Город'] == 'Казань') | (df['Продажи'] < 3)]
print("\n3. Товары в Казани или с продажами < 3:")
print(filtered[['Товар', 'Продажи', 'Город']])

Цепочка фильтров

Можно применять фильтры последовательно:

# Шаг 1: только Москва
df_moscow = df[df['Город'] == 'Москва']

# Шаг 2: только с продажами > 5
df_moscow_high = df_moscow[df_moscow['Продажи'] > 5]

# Шаг 3: только Ноутбуки
result = df_moscow_high[df_moscow_high['Товар'] == 'Ноутбук']

print(result)

Совет: Каждый шаг создаёт копию. Для больших данных лучше использовать комбинированное условие в одном фильтре.

Задачи для закрепления

Задача 1. Отфильтруй строки, где возраст больше 28.

Задача 2. Отфильтруй строки, где город «Москва» и зарплата больше 60000.

Задача 3. Используй query() для выборки людей с оценкой выше 4.5.

Задача 4. Отфильтруй строки, где город в списке ['Москва', 'Казань'].

Задача 5. Найди все строки, где имя содержит букву «а».

Ответы:

Задача 1.

filtered = df[df['Возраст'] > 28]

Задача 2.

filtered = df[(df['Город'] == 'Москва') & (df['Зарплата'] > 60000)]

Задача 3.

filtered = df.query('Оценка > 4.5')

Задача 4.

cities = ['Москва', 'Казань']
filtered = df[df['Город'].isin(cities)]

Задача 5.

filtered = df[df['Имя'].str.contains('а', na=False)]

Нюансы и подводные камни

Скобки в сложных условиях

Каждое условие в отдельные скобки:

# Неправильно
filtered = df[df['Возраст'] > 25 & df['Зарплата'] > 55000]

# Правильно
filtered = df[(df['Возраст'] > 25) & (df['Зарплата'] > 55000)]

Операторы & и | против and и or

В Pandas для булевых массивов нужно использовать & и |, а не and и or:

# Неправильно
filtered = df[df['Возраст'] > 25 and df['Зарплата'] > 55000]

# Правильно
filtered = df[(df['Возраст'] > 25) & (df['Зарплата'] > 55000)]

Проблемы с NaN

При фильтрации NaN ведёт себя как True. Используй .notna() или pd.isna():

# Исключаем пропуски
filtered = df[df['Колонка'].notna()]

Частые ошибки и как их избежать

Ошибка 1: Забыл скобки вокруг условий

# Ошибка
filtered = df[df['Возраст'] > 25 & df['Зарплата'] > 55000]

# Правильно
filtered = df[(df['Возраст'] > 25) & (df['Зарплата'] > 55000)]

Ошибка 2: Использовал and вместо &

# Ошибка
filtered = df[df['Возраст'] > 25 and df['Зарплата'] > 55000]

# Правильно
filtered = df[(df['Возраст'] > 25) & (df['Зарплата'] > 55000)]

Ошибка 3: Не учёл регистр в str.contains()

# Найдёт только с большой буквы
filtered = df[df['Имя'].str.contains('Анна')]

# Игнорируем регистр
filtered = df[df['Имя'].str.contains('анна', case=False)]

Шпаргалка

Что нужноКак пишется
Одно условиеdf[df['Возраст'] > 25]
Два условия (И)df[(условие1) & (условие2)]
Два условия (ИЛИ)df[(условие1) | (условие2)]
Отрицаниеdf[~(условие)]
Фильтр по спискуdf[df['Город'].isin(['Москва', 'СПб'])]
Поиск подстрокиdf[df['Имя'].str.contains('ан', case=False)]
Читаемый запросdf.query('Возраст > 25 and Зарплата > 55000')
Фильтр по датеdf[df['Дата'] >= '2024-01-01']
Исключить пропускиdf[df['Колонка'].notna()]

Заключение

Сегодня мы научились:

  • Фильтровать строки с помощью булевой индексации
  • Комбинировать условия через & (И) и | (ИЛИ)
  • Использовать query() для читаемых запросов
  • Применять isin() для фильтрации по списку
  • Искать подстроки в тексте через str.contains()
  • Фильтровать по датам

КВИЗ

Что дальше?

Оцените статью
IMI-DS - PYTHON LERNEN
Содержание
Оглавление ×