← Назад к вопросам

Какие знаешь методы очистки данных?

1.0 Junior🔥 181 комментариев
#Pandas и обработка данных#Python и программирование#Опыт работы и проекты

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Методы очистки данных (Data Cleaning) для Data Analyst

Очистка данных — это один из самых критичных процессов в аналитике. Грязные данные приводят к неверным выводам. По статистике, Data Analyst тратит 60-80% времени на очистку и подготовку данных.

1. Обработка пропущенных значений (Missing Values)

Типы пропусков

import pandas as pd
import numpy as np

# Создадим DataFrame с пропусками
df = pd.DataFrame({
    'name': ['Alice', 'Bob', np.nan, 'David'],
    'age': [25, None, 30, np.nan],
    'salary': [50000, 60000, np.nan, 70000]
})

print(df.isnull())
print(df.isnull().sum())  # Подсчет пропусков

Методы обработки

# 1. Удаление строк с пропусками
df_dropped = df.dropna()  # удалить все строки с хотя бы одним пропуском
df_dropped = df.dropna(subset=['name'])  # удалить если пропуск в 'name'

# 2. Удаление столбца, если много пропусков
df_cleaned = df.dropna(axis=1, thresh=len(df)*0.7)  # оставить столбцы с 70%+ данных

# 3. Заполнение констаными значениями
df_filled = df.fillna(0)  # заполнить нули
df_filled = df.fillna(df.mean())  # заполнить средним значением
df_filled = df.fillna(method='ffill')  # заполнить предыдущим значением (forward fill)

# 4. Интерполяция (для временных рядов)
df_interpolated = df.interpolate(method='linear')

# 5. Заполнение с условием
df['salary'] = df['salary'].fillna(df['salary'].median())

SQL подход

-- Выявить пропуски
SELECT COUNT(*) - COUNT(age) as missing_age
FROM users;

-- Удалить строки с пропусками
DELETE FROM users WHERE age IS NULL OR email IS NULL;

-- Заполнить значением
UPDATE users SET phone = '+7-000-0000' WHERE phone IS NULL;

-- Заменить на среднее
UPDATE products
SET price = (SELECT AVG(price) FROM products WHERE price IS NOT NULL)
WHERE price IS NULL;

2. Выявление и обработка выбросов (Outliers)

Метод межквартильного размаха (IQR)

# Выявление выбросов
Q1 = df['salary'].quantile(0.25)
Q3 = df['salary'].quantile(0.75)
IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

outliers = df[(df['salary'] < lower_bound) | (df['salary'] > upper_bound)]
print(f"Найденные выбросы: {len(outliers)}")

# Удаление выбросов
df_no_outliers = df[(df['salary'] >= lower_bound) & (df['salary'] <= upper_bound)]

# Или обрезание (capping)
df['salary'] = df['salary'].clip(lower=lower_bound, upper=upper_bound)

Метод Z-score

from scipy import stats

# Z-score: стандартное отклонение от среднего
z_scores = np.abs(stats.zscore(df['salary']))

# Выбросы > 3 стандартных отклонений
outliers = df[z_scores > 3]
df_clean = df[z_scores <= 3]

SQL для выявления выбросов

-- Выявить аномально высокие зарплаты
WITH salary_stats AS (
    SELECT 
        AVG(salary) as mean,
        STDDEV(salary) as stddev
    FROM employees
)
SELECT e.name, e.salary
FROM employees e, salary_stats s
WHERE ABS((e.salary - s.mean) / s.stddev) > 3;

3. Дублирование (Duplicates)

# Выявление дубликатов
duplicates = df[df.duplicated(keep=False)]
print(f"Дубликаты: {len(duplicates)}")

# Удаление дубликатов
df_unique = df.drop_duplicates()

# Удаление дубликатов по конкретным столбцам
df_unique = df.drop_duplicates(subset=['email'])

# Оставить первое/последнее вхождение
df_unique = df.drop_duplicates(subset=['email'], keep='first')
df_unique = df.drop_duplicates(subset=['email'], keep='last')

SQL

-- Выявить дубликаты
SELECT email, COUNT(*) as count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

-- Удалить дубликаты (оставить первый ID)
DELETE FROM users
WHERE id NOT IN (
    SELECT MIN(id)
    FROM users
    GROUP BY email
);

4. Нормализация и форматирование данных

Приведение к нижнему/верхнему регистру

df['email'] = df['email'].str.lower()
df['name'] = df['name'].str.upper()
df['status'] = df['status'].str.strip()  # удалить пробелы

Нормализация в диапазон [0, 1]

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df['salary_normalized'] = scaler.fit_transform(df[['salary']])

# Или вручную
df['salary_norm'] = (df['salary'] - df['salary'].min()) / (df['salary'].max() - df['salary'].min())

Стандартизация (Z-score normalization)

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
df['salary_standard'] = scaler.fit_transform(df[['salary']])

# Или вручную
df['salary_std'] = (df['salary'] - df['salary'].mean()) / df['salary'].std()

Форматирование дат

# Парсинг дат
df['order_date'] = pd.to_datetime(df['order_date'], format='%d/%m/%Y')

# Извлечение компонентов
df['year'] = df['order_date'].dt.year
df['month'] = df['order_date'].dt.month
df['day_of_week'] = df['order_date'].dt.day_name()

# Форматирование вывода
df['date_formatted'] = df['order_date'].dt.strftime('%Y-%m-%d')

5. Обработка категориальных данных

Исправление опечаток

# Заменить значения
df['status'] = df['status'].replace({
    'complited': 'completed',
    'panding': 'pending',
    'canelled': 'cancelled'
})

# Использовать FuzzyWuzzy для похожих строк
from fuzzywuzzy import fuzz
from fuzzywuzzy import process

# Найти близкие варианты
choices = ['completed', 'pending', 'cancelled']
df['status_corrected'] = df['status'].apply(
    lambda x: process.extractOne(x, choices)[0] if pd.notna(x) else None
)

One-Hot Encoding

# Преобразовать категории в бинарные столбцы
df_encoded = pd.get_dummies(df, columns=['status'])
print(df_encoded)

# Результат будет status_completed, status_pending, status_cancelled

Label Encoding

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
df['status_encoded'] = le.fit_transform(df['status'])
print(dict(zip(le.classes_, le.transform(le.classes_))))

6. Валидация данных

# Проверка типов
assert df['age'].dtype == 'int64', "Age должен быть целым числом"

# Проверка диапазонов
assert (df['age'] >= 0).all() and (df['age'] <= 120).all(), "Возраст вне диапазона"

# Проверка уникальности
assert df['email'].nunique() == len(df), "Есть дубликаты email"

# Проверка обязательных полей
assert df['email'].notna().all(), "Есть пропуски в email"

# Валидация email
import re
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
df['email_valid'] = df['email'].str.match(pattern)

SQL валидация

-- Проверить ограничения
ALTER TABLE users ADD CONSTRAINT check_age 
  CHECK (age >= 0 AND age <= 120);

-- Выявить невалидные данные
SELECT * FROM users WHERE age < 0 OR age > 120;

-- Удалить невалидные
DELETE FROM users WHERE email NOT LIKE '%@%';

7. Консолидация и трансформация данных

Объединение данных из разных источников

# Слияние DataFrame
df_result = pd.merge(df_users, df_orders, on='user_id', how='left')

# Конкатенация
df_combined = pd.concat([df_sales_2023, df_sales_2024])

# Объединение с удалением дубликатов
df_unique = pd.concat([df1, df2]).drop_duplicates()

Расстаянные операции

# Melt: преобразить столбцы в строки
df_melted = df.melt(id_vars=['name'], var_name='month', value_name='sales')

# Pivot: преобразить строки в столбцы
df_pivot = df.pivot_table(
    index='name',
    columns='month',
    values='sales',
    aggfunc='sum'
)

8. Автоматизация очистки

class DataCleaner:
    def __init__(self, df):
        self.df = df
    
    def remove_nulls(self, subset=None):
        self.df = self.df.dropna(subset=subset)
        return self
    
    def remove_duplicates(self, subset=None):
        self.df = self.df.drop_duplicates(subset=subset)
        return self
    
    def remove_outliers(self, column, method='iqr'):
        if method == 'iqr':
            Q1 = self.df[column].quantile(0.25)
            Q3 = self.df[column].quantile(0.75)
            IQR = Q3 - Q1
            self.df = self.df[
                (self.df[column] >= Q1 - 1.5 * IQR) & 
                (self.df[column] <= Q3 + 1.5 * IQR)
            ]
        return self
    
    def get_result(self):
        return self.df

# Использование
cleaner = DataCleaner(df)
df_clean = (cleaner
    .remove_nulls()
    .remove_duplicates()
    .remove_outliers('salary')
    .get_result())

Чеклист очистки данных

  • ✓ Проверить пропуски (NULL, NaN)
  • ✓ Выявить выбросы (outliers)
  • ✓ Удалить/обработать дубликаты
  • ✓ Нормализовать текст (case, пробелы)
  • ✓ Привести даты к единому формату
  • ✓ Исправить опечатки в категориях
  • ✓ Валидировать типы данных
  • ✓ Проверить диапазоны значений
  • ✓ Удалить ненужные столбцы
  • ✓ Документировать все изменения

Для Data Analyst качество данных определяет качество выводов. Никогда не пренебрегайте этапом очистки — это основа надежной аналитики.