Новости и статьи об искусственном интеллекте и нейросетях. Мы собираем и обрабатываем самую актуальную информацию из мира AI. О проекте

Статьи

7 трюков Python EDA для поиска ошибок данных

Семь практичных приемов на Python помогают в exploratory data analysis находить пропуски, выбросы, дубликаты и другие дефекты данных. На примере датасета сотрудников с искусственными ошибками показаны тепловые карты, IQR, лог-трансформы и корреляции. Методы сохраняют все детали и готовы к использованию в коде.

9 февраля 2026 г.
5 мин
20
7 приёмов Python EDA для поиска и исправления проблем с данными

Введение

Исследовательский анализ данных, или EDA, помогает подготовить почву для серьезного анализа или создания ИИ-систем на базе моделей машинного обучения. Проблемы с качеством данных вроде несоответствий часто решают позже в пайплайне, но на этапе EDA проще всего их заметить заранее. Так можно избежать скрытых искажений, падения точности моделей и ошибок в решениях.

Здесь собраны 7 приемов на Python, которые упрощают поиск и устранение разных дефектов данных на ранних шагах EDA. Для демонстрации используется набор данных о сотрудниках с специально добавленными проблемами. Перед тестами вставьте этот начальный код в среду разработки:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# PREAMBLE CODE THAT RANDOMLY CREATES A DATASET AND INTRODUCES QUALITY ISSUES IN IT
np.random.seed(42)
n = 1000
df = pd.DataFrame({
    "age": np.random.normal(40, 12, n).round(),
    "income": np.random.normal(60000, 15000, n),
    "experience_years": np.random.normal(10, 5, n),
    "department": np.random.choice([
        "Sales", "Engineering", "HR", "sales", "Eng", "HR "
    ], n),
    "performance_score": np.random.normal(3, 0.7, n)
})

# Randomly injecting data issues to the dataset
# 1. Missing values
df.loc[np.random.choice(n, 80, replace=False), "income"] = np.nan
df.loc[np.random.choice(n, 50, replace=False), "department"] = np.nan

# 2. Outliers
df.loc[np.random.choice(n, 10), "income"] *= 5
df.loc[np.random.choice(n, 10), "age"] = -5

# 3. Invalid values
df.loc[np.random.choice(n, 15), "performance_score"] = 7

# 4. Skewness
df["bonus"] = np.random.exponential(2000, n)

# 5. Highly correlated features
df["income_copy"] = df["income"] * 1.02

# 6. Duplicated entries
df = pd.concat([df, df.iloc[:20]], ignore_index=True)

df.head()

1. Поиск пропусков с помощью тепловых карт

В библиотеках вроде Pandas есть способы посчитать пропуски по столбцам, но тепловая карта через isnull() дает мгновенный обзор. Белые полосы вроде штрих-кода отметят каждый пропуск, распределенные по атрибутам горизонтально.

plt.figure(figsize=(10, 5))
sns.heatmap(df.isnull(), cbar=False)
plt.title("Missing Value Heatmap")
plt.show()

df.isnull().sum().sort_values(ascending=False)
Тепловая карта для поиска пропусков
Тепловая карта для поиска пропусков

2. Удаление дубликатов

Простой и надежный способ: посчитать дубликаты строк через duplicated(), а потом убрать их с помощью drop_duplicates(). По умолчанию остается первая копия, остальные удаляются. Можно выбрать keep="last" для последней или keep=False, чтобы стереть все копии. Выбор зависит от задачи.

duplicate_count = df.duplicated().sum()
print(f"Number of duplicate rows: {duplicate_count}")

# Remove duplicates
df = df.drop_duplicates()

3. Выбросы по методу межквартильного размаха

Метод IQR на основе статистики находит точки, сильно отстоящие от остальных, — потенциальные выбросы. Вот функция для числовых столбцов вроде "income":

def detect_outliers_iqr(data, column):
    Q1 = data[column].quantile(0.25)
    Q3 = data[column].quantile(0.75)
    IQR = Q3 - Q1
    lower = Q1 - 1.5 * IQR
    upper = Q3 + 1.5 * IQR
    return data[(data[column] < lower) | (data[column] > upper)]

outliers_income = detect_outliers_iqr(df, "income")
print(f"Income outliers: {len(outliers_income)}")

# Optional: cap them
Q1 = df["income"].quantile(0.25)
Q3 = df["income"].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
df["income"] = df["income"].clip(lower, upper)

4. Работа с несогласованными категориями

В отличие от выбросов в числах, проблемы с категориями возникают из-за ручных ошибок вроде разного регистра или вариаций в названиях. Нужно знание предметной области, чтобы выбрать правильные категории. Пример — приведение названий отделов к единому виду.

print("Before cleaning:")
print(df["department"].value_counts(dropna=False))

df["department"] = (
    df["department"]
    .str.strip()
    .str.lower()
    .replace({
        "eng": "engineering",
        "sales": "sales",
        "hr " : "hr"
    })
)

print("\nAfter cleaning:")
print(df["department"].value_counts(dropna=False))

5. Проверка и валидация диапазонов

Выбросы — это статистические аномалии, а недопустимые значения нарушают правила домена, например возраст не бывает отрицательным. Здесь отрицательные возраста заменяются на NaN — дальше их обработают как пропуски.

invalid_age = df[df["age"] < 0]
print(f"Invalid ages: {len(invalid_age)}")

# Fix by setting to NaN
df.loc[df["age"] < 0, "age"] = np.nan

6. Логарифмическое преобразование для скошенных данных

Скошенные признаки вроде "bonus" лучше привести к форме, близкой к нормальному распределению — это упрощает анализ для машинного обучения. Пример с логарифмом показывает распределение до и после.

skewness = df["bonus"].skew()
print(f"Bonus skewness: {skewness:.2f}")

plt.hist(df["bonus"], bins=40)
plt.title("Bonus Distribution (Original)")
plt.show()

# Log transform
df["bonus_log"] = np.log1p(df["bonus"])

plt.hist(df["bonus_log"], bins=40)
plt.title("Bonus Distribution (Log Transformed)")
plt.show()
Распределение бонусов до лог-преобразования
Распределение бонусов до логарифмического преобразования
Распределение бонусов после лог-преобразования
Распределение бонусов после логарифмического преобразования

7. Избыточные признаки через матрицу корреляций

Завершаем визуализацией: тепловая карта корреляций быстро покажет пары признаков с высокой связью — признак избыточности, которую стоит сократить. Приводятся топ-5 пар для ясности.

corr_matrix = df.corr(numeric_only=True)

plt.figure(figsize=(10, 6))
sns.heatmap(corr_matrix, annot=True, fmt=".2f", cmap="coolwarm")
plt.title("Correlation Matrix")
plt.show()

# Find high correlations
high_corr = (
    corr_matrix
    .abs()
    .unstack()
    .sort_values(ascending=False)
)
high_corr = high_corr[high_corr < 1]
print(high_corr.head(5))
Матрица корреляций для поиска избыточных признаков
Матрица корреляций для поиска избыточных признаков

Итог

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

Горячее

Загружаем популярные статьи...

7 Python-трюков для EDA: фикс ошибок в данных