Подготовка табличных данных в среде Python инструментарием Pandas
Основные приёмы подготовки данных с помощью Pandas
Обработка пропущенных значений
Как эффективно заполнить пропуски в числовых и категориальных столбцах?
Наиболее универсальным решением является комбинация fillna() с разными стратегиями в зависимости от типа столбца. Для числовых данных часто применяют заполнение медианой, для категориальных – модой. Это сохраняет распределение и не вносит сильных смещений.
import pandas as pd import numpy as np df = pd.DataFrame({ 'A': [1, 2, np.nan, 4], 'B': ['x', 'y', None, 'z'] }) # заполнение числового столбца медианой df['A'] = df['A'].fillna(df['A'].median()) # заполнение категориального столбца модой df['B'] = df['B'].fillna(df['B'].mode()[0])обработка больших данных python (обработка больших данных в python)
Типичная ошибка: попытка заполнить NaN значением, не соответствующим типу столбца (например, строкой в числовом столбце). Это приводит к ошибке TypeError. Решение – перед заполнением проверить тип данных через dtypes и применить соответствующую стратегию.
Как удалить строки с пропусками, если их доля мала?
Используется метод dropna() с параметрами axis=0 и how='any' (удаляет строку, если хотя бы один пропуск) или how='all' (только если все значения NaN).
df_clean = df.dropna(axis=0, how='any')очистка данных python (очистка данных в python)
Проблема: при большом количестве пропусков удаление может привести к потере значительной части данных и смещению выборки. Следует оценивать долю пропусков перед удалением (df.isnull().sum() / len(df)).
Как интерполировать пропуски во временных рядах?
Для последовательных данных с временной меткой хорошо работает interpolate(). По умолчанию используется линейная интерполяция, но можно задать метод method='quadratic' или method='spline' для более гладких кривых.
df_time = pd.DataFrame({ 'date': pd.date_range('2024-01-01', periods=5, freq='D'), 'value': [10, np.nan, 12, np.nan, 15] }).set_index('date') df_time['value'] = df_time['value'].interpolate()
Python подготовка данных (подготовка данных в python)
Важно: интерполяция работает только для числовых данных и требует упорядоченного индекса. Если индекс не отсортирован, необходимо выполнить sort_index() перед интерполяцией.
Удаление дубликатов
Как найти и удалить полные дубликаты строк?
Метод drop_duplicates() по умолчанию оставляет первое вхождение (keep='first'). Можно указать столбцы для проверки частичного дублирования через subset.
df = pd.DataFrame({'x': [1,2,1], 'y': ['a','b','a']}) df_no_dups = df.drop_duplicates(subset=['x'], keep='last')работа с dataframe python (работа с dataframe в python)
Типичная ошибка: забывают сбросить индекс после удаления, что может привести к неожиданному поведению при дальнейших операциях. Рекомендуется добавить .reset_index(drop=True).
Как выявить дубликаты без удаления?
Метод duplicated() возвращает булев массив. Его можно использовать для анализа: df[df.duplicated()] покажет все дублирующиеся строки.
duplicates_mask = df.duplicated(keep=False) # помечает все дубли, включая первое вхождениеPython работа с большими данными (работа с большими данными в python)
Преобразование типов данных
Как изменить тип столбца с объектного на числовой или дату?
Используется astype() для приведения к числу и pd.to_datetime() для даты. Важно обрабатывать ошибки преобразования с помощью параметра errors='coerce', который заменяет некорректные значения на NaN.
df['price'] = df['price'].astype(float) # если есть загрязнения, сначала использовать pd.to_numeric df['date'] = pd.to_datetime(df['date'], errors='coerce')структурированные данные python (структурированные данные в python)
Ошибка: при прямом astype(float) на строковом столбце с разделителями (например, '$10.50') возникает ValueError. Решение – предварительно очистить строку, удалив символы, или использовать pd.to_numeric с errors='coerce'.
Как преобразовать категориальный столбец в разреженный формат one-hot?
pd.get_dummies() создаёт бинарные столбцы для каждой категории. Для избежания мультиколлинеарности можно опустить первый уровень (drop_first=True).
df = pd.DataFrame({'cat': ['a','b','a','c']}) encoded = pd.get_dummies(df['cat'], prefix='cat')генерация данных python (генерация данных в python)
Проблема: при большом количестве уникальных категорий (сотни) получается много столбцов, что увеличивает память. В таких случаях стоит рассмотреть использование Category типа Pandas или применение LabelEncoder из sklearn.
Фильтрация и выборка
Как отфильтровать строки по сложному условию с несколькими столбцами?
Метод query() позволяет писать условия в строковом виде, что часто читаемее, чем логические маски. Поддерживает использование переменных через @.
threshold = 100 df_filtered = df.query('price > @threshold and quantity > 0')Python код символа (код символа в python)
Типичная ошибка: использование несуществующих столбцов в условии вызывает UndefinedVariableError. Необходимо проверять имена столбцов через df.columns.
Как выбрать строки по индексам или позициям?
loc для меток индекса, iloc для целочисленных позиций. Для срезов указываются начальная и конечная границы.
df.loc[0:2] # строки с метками индекса 0,1,2 (если индекс целый) df.iloc[0:2] # строки с позициями 0 и 1 (последняя не включается)код из файла python (код из файла python)
Объединение таблиц
Как объединить два набора данных по ключу?
merge() работает как SQL JOIN. Параметр how определяет способ: 'inner', 'left', 'right', 'outer'. Важно задавать ключи через left_on и right_on или on при одинаковых именах.
df1 = pd.DataFrame({'id': [1,2], 'val': ['a','b']}) df2 = pd.DataFrame({'id': [1,3], 'val2': ['c','d']}) merged = pd.merge(df1, df2, on='id', how='left')обработка данных на python (обработка данных на python)
Типичная ошибка: дублирование ключей в одном из датафреймов приводит к декартову произведению. Следует проверять уникальность ключей через duplicated() или использовать агрегацию перед merge.
Как объединить несколько таблиц по строкам или столбцам?
Для вертикального (по строкам) объединения используется pd.concat([df1, df2], axis=0), для горизонтального (по столбцам) – axis=1.
combined_rows = pd.concat([df1, df2], axis=0, ignore_index=True)обработка символьных данных python (обработка символьных данных в python)
Проблема: при concat по строкам могут не совпадать столбцы – недостающие заполняются NaN. Это может быть неожиданностью. Лучше использовать join='inner' или обработать после.
Группировка и агрегация
Как посчитать среднее по группам и добавить результат в исходный датафрейм?
Комбинация groupby() и transform() позволяет сохранить исходную структуру данных, добавив агрегированные значения в новый столбец.
df['avg_by_group'] = df.groupby('group')['value'].transform('mean')Python преобразование в строку (преобразование в строку в python)
Ошибка: использование transform с функцией, которая не векторизована, может быть медленной. Для пользовательских функций применяют transform(lambda x: ...), но это менее производительно.
Как создать сводную таблицу с несколькими агрегациями?
pivot_table() принимает параметры values, index, columns, aggfunc. Можно задать список функций агрегации.
pivot = df.pivot_table(values='sales', index='region', columns='product', aggfunc=['sum', 'mean'])Python как проверить строку (проверка строки в python)
Проблема: при наличии дублирующихся пар (index, columns) происходит ошибка или неопределённое поведение. Необходимо убедиться, что данные уникальны на уровне сводки, или задать aggfunc='first'.
Работа с категориальными переменными
Как преобразовать числовую переменную в категории?
pd.cut() разбивает интервал на заданное количество бинов или на конкретные границы. Метка может быть задана через labels.
df['age_group'] = pd.cut(df['age'], bins=[0, 18, 35, 60, 100], labels=['child','young','adult','senior'])как работать с данными в python (работа с данными в python)
Типичная ошибка: если значение выходит за пределы bins, оно становится NaN. Необходимо расширять границы или использовать include_lowest=True.
Как закодировать категориальные признаки для машинного обучения?
Помимо one-hot, можно использовать LabelEncoder из sklearn или pd.factorize() для присвоения числовых кодов. Также sklearn.preprocessing.OrdinalEncoder для нескольких столбцов.
from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df['cat_encoded'] = le.fit_transform(df['cat']) Проблема: LabelEncoder не подходит для порядковых признаков (вносит произвольный порядок). Для порядковых лучше задать явное отображение словарём.
Расширенные примеры подготовки данных
Использование цепочек методов для очистки
Современный подход – объединять несколько операций в цепочку с помощью .pipe() или последовательно. Ниже показана полная предобработка датафрейма с пропусками, дубликатами и неверными типами.
import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler # Исходные данные df = pd.DataFrame({ 'id': [1, 2, 3, 4, 2], 'name': ['Alice', 'Bob', None, 'David', 'Bob'], 'age': [25, np.nan, 30, 28, 40], 'salary': ['50000', '60000', '75000', 'NaN', '62000'], 'department': ['IT', 'HR', 'IT', 'IT', 'HR'] }) # Определим функции очистки def clean_salary(df): df['salary'] = pd.to_numeric(df['salary'], errors='coerce') return df def fill_missing(df): df['age'] = df['age'].fillna(df['age'].median()) df['name'] = df['name'].fillna('Unknown') return df def remove_duplicates(df): return df.drop_duplicates(subset=['id'], keep='first').reset_index(drop=True) def encode_department(df): df = pd.get_dummies(df, columns=['department'], prefix='dept') return df # Цепочка обработки df_cleaned = (df .pipe(clean_salary) .pipe(fill_missing) .pipe(remove_duplicates) .pipe(encode_department) ) print(df_cleaned) id name age salary dept_HR dept_IT 0 1 Alice 25.0 50000 0 1 1 2 Bob 28.0 60000 1 0 2 3 Unknown 30.0 75000 0 1 3 4 David 28.0 NaN 0 1
В результате удалён дубликат (id=2), пропущенные значения заполнены, зарплата приведена к числу, отдел закодирован one-hot. Пропуск в salary остался – его можно обработать далее, например, импутацией медианой.
Масштабирование числовых признаков
Для моделей, чувствительных к масштабу (SVM, kNN), необходимо нормализовать данные. Пример с MinMaxScaler и добавлением результата в датафрейм.
df_num = df_cleaned[['age', 'salary']].copy() scaler = MinMaxScaler() scaled = scaler.fit_transform(df_num) df_scaled = pd.DataFrame(scaled, columns=['age_scaled', 'salary_scaled']) df_final = pd.concat([df_cleaned, df_scaled], axis=1) print(df_final[['age', 'age_scaled', 'salary', 'salary_scaled']]) age age_scaled salary salary_scaled 0 25.0 0.000000 50000.0 0.000000 1 28.0 0.600000 60000.0 0.333333 2 30.0 1.000000 75000.0 0.833333 3 28.0 0.600000 NaN NaN
Обратите внимание: NaN в salary_scaled – результат масштабирования, где входное значение было NaN. Это может потребовать дополнительной импутации перед масштабированием.
Обработка временных рядов с интерполяцией и resampling
Для данных с временной меткой часто требуется смена частоты. Пример почасового набора данных с пропусками.
dates = pd.date_range('2024-01-01', periods=8, freq='H') values = [1, np.nan, 3, 4, np.nan, 6, 7, 8] ts = pd.Series(values, index=dates, name='measure') # Ресемплинг до 2 часов с агрегацией среднего ts_resampled = ts.resample('2H').mean().interpolate() print('Исходный:', ts.values, sep='
') print('После ресемплинга и интерполяции:', ts_resampled.values, sep='
') Исходный: [ 1. nan 3. 4. nan 6. 7. 8.] После ресемплинга и интерполяции: [1. 3.5 5. 7.5]
Интерполяция после агрегации даёт плавный переход между точками.
Объединение нескольких датафреймов с разными ключами
Пример сложного слияния с использованием pd.merge_asof для нечеткого совпадения по времени.
price = pd.DataFrame({'time': pd.to_datetime(['2024-01-01 10:00', '2024-01-01 10:15', '2024-01-01 10:30']), 'price': [100, 101, 102]}) trade = pd.DataFrame({'time': pd.to_datetime(['2024-01-01 10:10', '2024-01-01 10:20']), 'volume': [10, 20]}) # merge_asof подбирает ближайший момент из price к каждому trade merged = pd.merge_asof(trade, price, on='time', tolerance=pd.Timedelta('5min')) print(merged) time volume price 0 2024-01-01 10:10:00 10 100.0 1 2024-01-01 10:20:00 20 101.0
Этот метод особенно полезен для финансовых данных, где торговые сделки не совпадают по времени с котировками.
Агрегация с пользовательской функцией и оконными операциями
Группировка с применением скользящего среднего внутри каждой группы.
df = pd.DataFrame({ 'group': ['A','A','A','B','B','B'], 'value': [1, 2, 3, 10, 11, 12] }) df['rolling_mean'] = df.groupby('group')['value'].transform(lambda x: x.rolling(2, min_periods=1).mean()) print(df) group value rolling_mean 0 A 1 1.0 1 A 2 1.5 2 A 3 2.5 3 B 10 10.0 4 B 11 10.5 5 B 12 11.5
Оконные функции полезны для создания признаков с временной или порядковой зависимостью.