Фильтрация и условные запросы в Pandas

Фильтрация данных — одна из самых распространённых операций в анализе данных. Pandas предоставляет богатый функционал условных запросов, который позволяет фильтровать данные по различным условиям. В этом разделе подробно рассматриваются различные методы фильтрации данных.


Базовая условная фильтрация

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

Пример

import pandas as pd

# Создание тестовых данных
df = pd.DataFrame({
    "Имя": ["Чжан Сань", "Ли Сы", "Ван У", "Zhao Liu", "Qian Qi"],
    "Возраст": [25, 30, 28, 35, 22],
    "Город": ["Пекин", "Шанхай", "Гуанчжоу", "Beijing", "Shenzhen"],
    "Зарплата": [12000, 15000, 11000, 18000, 9000],
    "Department": ["Tech", "Sales", "Tech", "Operations", "Tech"]
})

print(Исходные данные:)
print(df)
print()

# Фильтрация по равенству
print("City equals Beijing:")
print(df[df["City"] == "Beijing"])
print()

# Фильтрация по неравенству
print("Город не равен Пекину:")
print(df[df["City"] != "Beijing"])
print()

# Больше и меньше
print("Зарплата больше 12000:")
print(df[df["Salary"] > 12000])
print()

# Строковое условие
print("Имя содержит 'San':")
print(df[df["Name"].str.contains("San")])

Объединение нескольких условий

Пример

import pandas as pd

df = pd.DataFrame({
    "Имя": ["Чжан Сань", "Ли Сы", "Ван У", "Zhao Liu", "Qian Qi"],
    "Возраст": [25, 30, 28, 35, 22],
    "Город": ["Пекин", "Шанхай", "Гуанчжоу", "Beijing", "Shenzhen"],
    "Зарплата": [12000, 15000, 11000, 18000, 9000],
    "Department": ["Tech", "Sales", "Tech", "Operations", "Tech"]
})

# Условие AND: используйте оператор &
print("Пекин и Зарплата>10000:")
print(df[(df["City"] == "Beijing") & (df["Salary"] > 10000)])
print()

# Условие ИЛИ: используйте оператор |
print("Технический отдел или Salary>15000:")
print(df[(df["Department"] == "Tech") | (df["Salary"] > 15000)])
print()

# Условие НЕ: используйте оператор ~
print("Не технический отдел:")
print(df[~(df["Department"] == "Tech")])
print()

# Сложная комбинация
print("(Пекин и Age>25) или (Шанхай):")
print(df[((df["City"] == "Beijing") & (df["Age"] > 25)) | (df["City"] == "Shanghai")])

При объединении нескольких условий каждое условие должно быть заключено в круглые скобки, и используйте&(И),|(ИЛИ) для соединения, и нельзя использовать в Pythonand、orключевые слова.


isin и where

isin-фильтрация

Пример

import pandas as pd

df = pd.DataFrame({
    "Имя": ["Чжан Сань", "Ли Сы", "Ван У", "Zhao Liu", "Qian Qi"],
    "Город": ["Пекин", "Шанхай", "Гуанчжоу", "Beijing", "Shenzhen"],
    "Department": ["Tech", "Sales", "Tech", "Operations", "Tech"]
})

# Фильтрация внутри списка
print("Город — Пекин или Шанхай:")
print(df[df["City"].isin(["Beijing", "Shanghai"])])
print()

# Не в списке
print("Город — не Пекин и не Шанхай:")
print(df[~df["City"].isin(["Beijing", "Shanghai"])])
print()

# isin для нескольких столбцов
df2 = pd.DataFrame({
    "Город": ["Пекин", "Шанхай"],
    "Department": ["Tech", "Sales"]
})
print("Соответствует и городу, и отделу:")
print(df[df[["City", "Department"]].isin(df2).all(axis=1)])

where Condition

Пример

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "A": [1, 5, 3, 7],
    "B": [4, 2, 8, 3]
})

# where: сохранять значения, удовлетворяющие условию, остальные устанавливать в NaN или заданное значение
print("Значения больше 3 сохраняются, остальные устанавливаются в 0:")
result = df.where(df > 3, 0)
print(result)
print()

# Использовать другой DataFrame в качестве условия
other = pd.DataFrame({
    "A": [True, False, True, False],
    "B": [False, True, False, True]
})
print("Фильтрация на основе DataFrame условия:")
print(df.where(other, -1))

Фильтрация строк

Пример

import pandas as pd

df = pd.DataFrame({
    "Имя": ["Чжан Сань", "Ли Сы", "Ван У", "Чжао Лю", "Сунь Ци"],
    "Город": ["Пекин", "Шанхай", "Гуанчжоу", "Шэньчжэнь", "Ханчжоу"],
    "Email": ["[email protected]", "[email protected]", "[email protected]",
             "[email protected]", "[email protected]"]
})

# Содержит
print("Город содержит 'Пекин':")
print(df[df["City"].str.contains("Пекин")])
print()

# Начинается с / Заканчивается на
print("Электронная почта начинается с zhang:")
print(df[df["Email"].str.startswith("zhang")])
print()

# Совпадение регулярного выражения
print("Длина имени пользователя электронной почты больше 4:")
print(df[df["Email"].str.extract(r"(\w+)@")[0].str.len() > 4])
print()

# Сопоставление с несколькими шаблонами
print("Город начинается с Bei, Shang, Guang или Shen:")
print(df[df["City"].str.contains("^Bei|^Shang|^Guang|^Shen")])

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

Пример

import pandas as pd

df = pd.DataFrame({
    "Имя": ["Чжан Сань", "Ли Сы", "Ван У", "Zhao Liu", "Qian Qi"],
    "Возраст": [25, 30, 28, 35, 22],
    "Зарплата": [12000, 15000, 11000, 18000, 9000]
})

# Фильтрация диапазона
print("Возраст между 25 и 30 (включительно):")
print(df[df["Age"].between(25, 30)])
print()

# Фильтрация по квантилям
q1 = df["Salary"].quantile(0.25)
q3 = df["Salary"].quantile(0.75)
print(f"Зарплата между 25% и 75% ({q1}-{q3}):")
print(df[df["Salary"].between(q1, q3)])
print()

# Верхние/нижние N строк
print("Топ-3 зарплаты:")
print(df.nlargest(3, "Salary"))
print()

print("2 самые низкие зарплаты:")
print(df.nsmallest(2, "Salary"))

Фильтрация временных данных

Пример

import pandas as pd

# Создание данных временного ряда
df = pd.DataFrame({
    "Date": pd.date_range("2024-01-01", periods=10, freq="D"),
    "Sales": [100, 120, 90, 150, 200, 180, 110, 130, 170, 190]
})
df = df.set_index("Date")

print("Данные временного ряда:")
print(df)
print()

# Фильтрация по дате
print("Данные за 2024-01-05:")
print(df.loc["2024-01-05"])
print()

# Фильтрация по диапазону дат
print("С 2024-01-03 по 2024-01-07:")
print(df.loc["2024-01-03":"2024-01-07"])
print()

# Использование truncate (более эффективное срезание)
print("Фильтрация truncate:")
print(df.truncate(before="2024-01-03", after="2024-01-07"))

Метод query

queryМетод обеспечивает более лаконичный подход к фильтрации в стиле SQL.

Пример

import pandas as pd

df = pd.DataFrame({
    "FullName": ["Zhang San", "Li Si", "Wang Wu", "Чжао Лю"],
    "Возраст": [25, 30, 28, 35],
    "Город": ["Пекин", "Шанхай", "Гуанчжоу", "Пекин"],
    "Зарплата": [12000, 15000, 11000, 18000]
})

# Использование метода query
print("Age>26 and City='Beijing':")
print(df.query("Age > 26 and City == 'Beijing'"))
print()

# Использование переменных
min_age = 26
city = "Beijing"
print(f"Age>{min_age} and City={city}:")
print(df.query("Age > @min_age and City == @city"))
print()

# Если в именах столбцов есть пробелы, используйте обратные кавычки
df2 = df.rename(columns={"FullName": "Full Name"})
print("Когда имя столбца содержит пробел:")
print(df2.query("`Full Name` == 'Zhang San'"))

Распространённые проблемы

1. Ошибка при объединении условий

При фильтрации с несколькими условиями используйте скобки для уточнения приоритета и используйте&、|а неand、or。

2. Строки содержат null-значения

Используйтеstr.containsПеред [использованием] необходимо обработать значения null:df[df["列"].str.contains("x", na=False)]

3. Фильтрация по индексу

Если DataFrame имеет пользовательский индекс, обратите внимание наlocиilocразницу.

Для сложных запросов с несколькими условиями,queryСинтаксис этого метода ближе к естественному языку, что делает код более читаемым. Когда объём данных большой,locпри объединении с булевыми массивами он обычноqueryбыстрее.

Другие расширения