Pandas заполнение пропусков: 5 методов для чистых данных
Содержание статьи
- Основные методы заполнения пропусков в pandas
- Заполнение пропусков фиксированным значением через fillna
- Метод interpolate для интерполяции пропущенных значений
- Заполнение пропусков статистическими показателями
- Заполнение пропусков средним значением по столбцу
- Заполнение пропусков медианой и модой в pandas
- Заполнение пропусков предыдущим или следующим значением
- Метод ffill: заполнение пропусков предыдущим значением
- Метод bfill: заполнение пропусков следующим значением
- Заполнение пропусков в зависимости от группы данных
- Заполнение пропусков средним по группе с groupby и transform
- Заполнение пропусков по условию с apply и lambda-функциями
- Практические примеры и частые ошибки при работе с пропусками
- Пример: смешанный датасет
- Типичные ошибки новичков
- Пример заполнения пропусков в датафрейме с числовыми данными
- Ошибки при заполнении пропусков и как их избежать
Основные методы заполнения пропусков в pandas
При работе с реальными данными пустые ячейки встречаются постоянно. Библиотека предлагает несколько базовых подходов для их обработки. Выбор конкретного способа зависит от типа данных и смысловой нагрузки столбца.
- Метод fillna() — универсальный инструмент, позволяющий подставить конкретное значение, например, ноль или среднее арифметическое.
- Интерполяция — вычисляет промежуточные значения на основе соседних точек, что удобно для временных рядов.
- bfill() и ffill() — заполняют пустоты предыдущими или последующими значениями соответственно.
Каждый из этих приёмов решает свою задачу, и важно понимать, когда какой уместно применить, чтобы не исказить картину данных.
Заполнение пропусков фиксированным значением через fillna
Метод fillna() позволяет подставить вместо отсутствующих ячеек конкретную константу. Это самый прямолинейный способ, когда пробелы в данных означают, например, «ноль» или «не указано».
Синтаксис прост: df.fillna(0) заменит все NaN на ноль. Если нужно обработать только отдельный столбец, укажите его: df['цена'].fillna(0). Для разных колонок можно передать словарь значений: df.fillna({'возраст': 30, 'доход': 0}).
Важный нюанс: по умолчанию создаётся копия, а исходный датафрейм не меняется. Чтобы применить изменения на месте, используйте параметр inplace=True или переприсвойте результат.
Метод interpolate для интерполяции пропущенных значений
Когда данные меняются плавно, например, температура или курс валют, логичнее не просто вставлять среднее, а вычислить промежуточную точку. Метод interpolate() в pandas делает именно это — он строит линию между известными соседними наблюдениями и подставляет недостающее число.
По умолчанию используется линейная логика: значение лежит ровно посередине между предыдущим и следующим. Но есть и другие режимы:
method='time'— учитывает реальный интервал времени между индексами;method='quadratic'— строит параболу по нескольким точкам;limit— ограничивает число подряд идущих пропусков, которые будут заполнены.
Такой подход хорошо работает для временных рядов, но для категориальных признаков он не подходит — там лучше использовать ffill() или модальное значение.
Заполнение пропусков статистическими показателями
Когда в данных не хватает значений, часто прибегают к простым числовым характеристикам. Вместо удаления строк разумнее подставить среднее арифметическое или медиану. Выбор зависит от распределения: для нормального подойдёт среднее, при наличии выбросов — медиана. Также используют моду для категориальных колонок. Такой подход сохраняет объём выборки и не требует сложных вычислений. Однако стоит помнить: подобная замена уменьшает дисперсию, что иногда искажает результаты анализа.
Заполнение пропусков средним значением по столбцу
Когда в данных встречаются пустые ячейки, часто прибегают к самому простому приёму — подстановке средней арифметической величины. Для этого в pandas существует метод fillna(), который в паре с mean() даёт быстрый результат. Сначала вычисляем среднее по нужной колонке, затем подставляем его вместо пропусков. Такой подход уместен для числовых признаков, где распределение близко к нормальному, и не искажает общую картину.
Пример кода:
df['колонка'] = df['колонка'].fillna(df['колонка'].mean())
Однако стоит помнить: если выбросы значительны, среднее может «уехать». В таких случаях лучше взять медиану — она устойчивее к аномалиям. Выбор зависит от задачи и природы данных.
Заполнение пропусков медианой и модой в pandas
Когда в данных встречаются пропуски, не всегда уместно заменять их средним арифметическим — выбросы сильно искажают результат. Для устойчивости к аномалиям чаще прибегают к медиане, а для категориальных колонок — к моде. В pandas заполнение пропусков реализуется через метод fillna(), куда передаётся вычисленное значение.
На практике это выглядит так:
- Для числового признака:
df['col'].fillna(df['col'].median())— надёжный вариант при скошенном распределении. - Для текстового или бинарного поля:
df['col'].fillna(df['col'].mode()[0])— берётся самое частое значение.
Удобно применять эти приёмы вместе с группировкой, когда медиана считается отдельно для каждой категории. Так сохраняется внутренняя логика данных, а не усредняется всё подряд.
Заполнение пропусков предыдущим или следующим значением
Когда данные имеют временную структуру, удобно применять метод ffill() — он переносит последнее известное наблюдение вниз, заполняя пустоты. Обратная операция выполняется через bfill(), которая берёт следующее значение. Такой подход часто используют для котировок или показаний датчиков, где пропуск логично заменить соседней величиной. Однако стоит помнить: если разрыв велик, результат может исказить реальную картину. Перед применением стоит оценить длину серии пропусков, чтобы не получить ступенчатый график вместо плавного тренда.
Метод ffill: заполнение пропусков предыдущим значением
Метод ffill() в pandas распространяет последнее известное наблюдение вниз по столбцу. Это удобно для временных рядов, где пропуск означает «значение не изменилось». Например, при фиксации показаний датчиков раз в минуту с редкими сбоями записи.
Альтернатива — bfill(), заполняющая пробелы последующими данными. Выбор зависит от логики: если пропуск в начале ряда, обратное заполнение часто уместнее.
Важно помнить: метод не интерполирует, а просто копирует предыдущее значение. Для плавных трендов это может исказить картину.
Метод bfill: заполнение пропусков следующим значением
Обратная по логике операция — bfill() — подтягивает на пустые позиции данные, идущие следом. Это удобно, когда запись опаздывает: например, в журнале событий метка времени проставлена только в конце блока. Метод работает по оси строк, но при желании его можно применить и к столбцам, указав параметр axis=1. Важно помнить: если пропуск находится в самом конце таблицы, он останется незаполненным — для таких случаев стоит комбинировать подход с ffill() или интерполяцией.
Заполнение пропусков в зависимости от группы данных
При работе с реальными датасетами часто встречается ситуация, когда пропуски распределены неравномерно. Например, в одной категории товаров отсутствует треть значений, а в другой — лишь пара записей. В таких случаях разумно обрабатывать каждую группу отдельно, а не применять единый подход ко всему фрейму.
Удобный приём — использовать groupby() в связке с трансформацией. Это позволяет заполнить пустоты средним или медианой, рассчитанными строго внутри своей категории. Такой метод сохраняет внутреннюю структуру данных и не искажает статистику для отдельных сегментов.
На практике это выглядит так:
df['значение'] = df.groupby('категория')['значение'].transform(lambda x: x.fillna(x.median()))
Подобный подход особенно полезен, когда группы сильно различаются по масштабу. Если же разброс внутри категорий незначителен, можно ограничиться глобальным заполнением — это проще и быстрее.
Заполнение пропусков средним по группе с groupby и transform
Когда данные сгруппированы по категориям, глобальное среднее часто не подходит — корректнее взять медиану или среднее внутри каждой группы. Метод transform позволяет подставить агрегированное значение в исходный датафрейм, сохраняя его форму.
df['значение'] = df.groupby('категория')['значение'].transform(lambda x: x.fillna(x.mean()))
Такой подход работает и с другими функциями: median(), sum() или пользовательскими лямбда-выражениями. Главное — не забыть про fillna внутри, иначе пропуски останутся.
Заполнение пропусков по условию с apply и lambda-функциями
Когда логика восстановления данных зависит от значений в соседних колонках, стандартные методы вроде fillna() не всегда подходят. Здесь выручает связка apply() с анонимной функцией. Например, если в одной колонке указан регион, а в другой — отсутствует цена, можно задать правило: для Москвы подставлять одно значение, для регионов — другое.
Алгоритм прост:
- Создаёте функцию, которая принимает строку целиком (через
axis=1). - Внутри проверяете условие через
ifилиnp.where(). - Возвращаете либо исходное значение, либо подстановочное.
Такой подход даёт гибкость: можно комбинировать проверки по нескольким полям, использовать словари соответствий или даже вызывать внешние сервисы для расчёта. Главное — не забывать, что функция должна быть чистой и не менять исходный DataFrame побочно.
Практические примеры и частые ошибки при работе с пропусками
На практике чаще всего спотыкаются о три вещи: попытка заполнить всё подряд одним методом, игнорирование типа данных и забывчивость про параметр inplace. Рассмотрим типичный сценарий.
Пример: смешанный датасет
Предположим, есть таблица с числовыми показателями и категориальным столбцом. Если применить ко всей таблице среднее арифметическое, то текстовые поля просто сломаются. Логичнее разбить задачу:
- Для чисел — медиана или интерполяция.
- Для категорий — мода или отдельная метка «неизвестно».
Типичные ошибки новичков
| Ошибка | Чем грозит |
|---|---|
| Заполнение средним при наличии выбросов | Сильное смещение распределения |
Забытый параметр inplace=True |
Изменения не сохраняются, код «молча» работает впустую |
| Не проверено количество пустот до и после | Трудно понять, сработал ли метод вообще |
Совет: всегда фиксируйте долю пропусков до начала манипуляций и после. Это убережёт от ложного ощущения, что данные чистые.
Пример заполнения пропусков в датафрейме с числовыми данными
Допустим, имеется таблица с показателями продаж за несколько месяцев, где часть значений отсутствует. Проще всего применить метод fillna(), указав конкретное число — например, ноль или среднее арифметическое по столбцу.
df['выручка'].fillna(df['выручка'].mean(), inplace=True)
Такой подход уместен, когда пробелы не критичны и не искажают общую картину. Для более точной интерполяции используют interpolate(), который подставляет промежуточные величины на основе соседних строк.
Ошибки при заполнении пропусков и как их избежать
Частая оплошность — слепо применять один и тот же метод ко всем колонкам датафрейма. Числовые показатели и категориальные признаки требуют разного подхода: где-то уместна медиана, а где-то — мода. Игнорирование этого ведёт к смещению распределений.
Не менее опасна ситуация, когда пропуски не случайны, а зависят от других переменных. В таком случае простое удаление строк или вставка среднего значения создаёт систематическую ошибку. Стоит сначала визуализировать паттерн отсутствия данных.
Проверяйте результат после трансформации: сравнивайте статистики до и после. Если разброс значений резко изменился, вероятно, выбранная стратегия не подходит. Лучше потратить время на анализ природы пустот, чем потом переделывать всю работу.
