My deep learning

Обработка пропусков в Pandas

Есть несколько стратегий индикации пропусков в данных

Использование некоего значения-индикатора

К примеру, можно использовать число -9999 или редко встречающееся сочетание битов. Более часто встречающийся способ — условное обозначение через NaN. NaN — это специальное значение, определенное спецификацией IEEE для чисел с плавающей точкой и используется во многих ЯП.

У метода есть ограничения. Во-первых использование значений индикаторов может привести к дополнительным не оптимизированным расчетам. Во-вторых NaN доступен не для всех типов данных.

Использование масок

Можно создать отдельный булевый массив, индицирующий пропущенные значения. В ряде языков выделяется отдельный бит для разметки пропусков в массиве данных локально. Оба подхода влекут за собой перерасход памяти.

Как это реализовано в Pandas?

Pandas построена на NumPy, в котором отсутствует понятие пропуска для всех данных кроме данных с плавающей точкой. NumPy поддерживает маски, но использование такого подходжа в Pandas влечет значительные накладные расходы на хранение, вычисление и поддержку кода.

В итоге в Pandas используется:

  • индикаторы-числа

  • NaN из Numpy

  • None из Python

Объект None

None - объект python. Его нельзя использовать в NumPy и во всех производных массивах Pandas. None используется только в массивах с типом object. Когда мы создаем массив, используя None, автоматически создается массив с типом object.

Тип object означает, что NumPy не смог установить тип объектов массива, единственное что он знает — это то, что это объекты python. Операции с такими массивами будут производится на уровне языка python, т.е. со всеми накладными расходами, присущими языку с динамической типизацией. Оптимизация NumPy работать не будет.

Кроме того, функции агрегирования по массиву, например, massive.sum() или massive.min() выбросят ошибку, так как операции между численным значением и значением None не определены

Объект NaN

Объект NaN определяет отсутствие числового значения с плавающей точкой. Это вызывает некоторые проблемы — если NaN попадает в массив, все данные приводятся к числам с плавающей точкой. Кроме того, все операции с NaN приводят к NaN, в том числе и функции агрегирования.

Не забудьте, что для вызова объекта NaN нужен NumPy

0 / numpy.nan
>>> nan

Nan и None

Pandas преобразует None в NaN, если оба будут встречены в одном массиве. Естественно, осуществляется и повышающее преобразование с приведением всех непустых числовых значений к числу с плавающей точкой, а всех остальных к NaN.

pd.Series([1, np.nan, 3, None])
>>> 0    1.0
... 1    NaN
... 2    3.0
... 3    NaN
... dtype: float64

x = pd.Series([1, 2, 3], dtype='int8')
x
>>> 0    1
... 1    2
... 2    3
... dtype: int8

x[0] = None
x
>>> 0    NaN
... 1    2.0
... 2    3.0
... dtype: float64

Правила повышающих преобразований типов в Pandas (строки всегда хранятся как object)

Typeclass Conversion When Storing NAN NAN Sentinel Value
floating No change np.nan
object No change None or np.nan
integer Cast to float64 np.nan
boolean Cast to object None or np.nan

Операции над пустыми значениями

В Pandas доступно несколько методов:

  • isnull() — генерирует булеву маску для отсутствующих значений

  • notnull() — тоже для непустых

  • dropna() — фильтрация данных по отсутствующим значениям

  • fillna() — замена пропусков с возвратом копии

Методы доступны как для объектов Series так и для dataFrame (с выбором измерения).

Кроме того, для dropna() ожно задать дополнительные параметры. how=’any’ задан по дефолту, можно переопределить как ‘all’ — будут отбрасываться только полностью пустые строки/столбцы. thresh задает минимальное значение непустых значений, выше которого строки/столбцы не отбрасываются.

Для fillna() доступно несколько аргументов. method=’ffill’ и method=’bfill’ определяют какими значениями будут заполняться пропуски (предыдущими или последующими в массиве).

Подробнее fillna() и dropna()

Поделиться статьей

Все статьи с тегом pandas

Этот проект поддерживается KonstantinKlepikov