Сообщить об ошибке.

Методы pandas для работы с None и NaN в DataFrame/Series

Поиск/удаление/замена пустых значений в pandas

В материале рассмотрены методы объектов DataFrame и Series, которые позволяют искать/удалять/заменять недостающие (пустые) данные (также называемые NA) в pandas.

Содержание:

  • Метод DataFrame.isna() ищет None или numpy.NaN/NA в DataFrame;
  • Метод Series.isna() ищет None или numpy.NaN/NA в Series;
  • Метод DataFrame.notna() ищет значения, отличные от None или numpy.NaN/NA в DataFrame;
  • Метод Series.notna() ищет значения, отличные от None или numpy.NaN/NA в Series;
  • Метод DataFrame.isnull() ищет None или numpy.NaN/NA в DataFrame;
  • Метод Series.isnull() ищет None или numpy.NaN/NA в Series;
  • Метод DataFrame.notnull() ищет значения, отличные от None или numpy.NaN/NA в DataFrame;
  • Метод Series.notnull() ищет значения, отличные от None или numpy.NaN/NA в Series;
  • Метод DataFrame.dropna() удаляет None или numpy.NaN/NA из DataFrame;
  • Метод Series.dropna() удаляет None или numpy.NaN/NA из Series;
  • Метод DataFrame.fillna() заполняет значения None/NA/NaN в DataFrame;
  • Метод Series.fillna() заполняет значения None/NA/NaN в Series;
  • Метод DataFrame.interpolate() заполняет значения None/NA/NaN в DataFrame, используя метод интерполяции;
  • Метод Series.interpolate() заполняет значения None/NA/NaN в Series, используя метод интерполяции.

- DataFrame.isna():
- Series.isna():

Методы DataFrame.isna() иSeries.isna() находят значения, такие как None или numpy.NaN в DataFrame и Series соответственно.

Возвращают логический объект того же размера - маску логических значений для каждого элемента в DataFrame/Series, которая указывает, является ли элемент значением NA.

Значения NA, такие как None или numpy.NaN, сопоставляется со значениями True. Все остальное сопоставляется со значениями False.

Внимание! Такие символы, как пустые строки '' или numpy.inf, не считаются значениями NA (если не установлено значение pandas.options.mode.use_inf_as_na=True).

Как посмотреть записи в DataFrame являющиеся NA.

>>> import pandas as pd
>>> import numpy as np
df = pd.DataFrame(dict(age=[5, 6, np.nan],
                       born=[pd.NaT, pd.Timestamp('1939-05-27'),
                             pd.Timestamp('1940-04-25')],
                       name=['Alfred', 'Batman', ''],
                       toy=[None, 'Batmobile', 'Joker']))
>>> df
#    age       born    name        toy
# 0  5.0        NaT  Alfred       None
# 1  6.0 1939-05-27  Batman  Batmobile
# 2  NaN 1940-04-25              Joker

# ячейки с `NA` будут `True`
>>> df.isna()
#      age   born   name    toy
# 0  False   True  False   True
# 1  False  False  False  False
# 2   True  False  False  False

Чтобы посмотреть строки DataFrame, содержащие NA можно использовать метод DataFrame.any():

>>> df.isna().any(axis=1)
# 0     True
# 1    False
# 2     True
# dtype: bool

Теперь, используя "логическую индексацию" выведем сами строки DataFrame, содержащие NA:

>>> df.loc[df.isna().any(axis=1)]
#    age       born    name    toy
# 0  5.0        NaT  Alfred   None
# 2  NaN 1940-04-25          Joker

Передавая отрицание ~ логической индексации, можно вывести строки, которые НЕ содержат NA:

>>> df.loc[~df.isna().any(axis=1)]
#    age       born    name        toy
# 1  6.0 1939-05-27  Batman  Batmobile

Покажем, какие записи в Series являются NA.

>>> ser = pd.Series([5, 6, np.nan])
>>> ser
# 0    5.0
# 1    6.0
# 2    NaN
# dtype: float64

>>> ser.isna()
# 0    False
# 1    False
# 2     True
# dtype: bool

# и применяем логическую индексацию
>>> ser[ser.isna()]
# 2   NaN
# dtype: float64

# строки НЕ содержащие `NA`
>>> ser[~ser.isna()]
# 0    5.0
# 1    6.0
# dtype: float64

- DataFrame.notna():
- Series.notna():

Методы DataFrame.notna() и Series.notna() находят НЕ ПУСТЫЕ значения в DataFrame и Series соответственно.

Возвращает логический объект того же размера - маску логических значений для каждого элемента в DataFrame/Series, которая указывает, на НЕ ПУСТЫЕ значения.

НЕ ПУСТЫЕ значения сопоставляются с True . Значения NA, такие как None или numpy.NaN, будут сопоставлены значениям False.

Внимание! Символы, такие как '' пустые строки' или numpy.inf, не считаются значениями NA (если только не установлено pandas.options.mode.use_inf_as_na=True).

df = pd.DataFrame(dict(age=[5, 6, np.nan],
                       born=[pd.NaT, pd.Timestamp('1939-05-27'),
                             pd.Timestamp('1940-04-25')],
                       name=['Alfred', 'Batman', ''],
                       toy=[None, 'Batmobile', 'Joker']))
>>> df
#    age       born    name        toy
# 0  5.0        NaT  Alfred       None
# 1  6.0 1939-05-27  Batman  Batmobile
# 2  NaN 1940-04-25              Joker

>>> df.notna()
#      age   born  name    toy
# 0   True  False  True  False
# 1   True   True  True   True
# 2  False   True  True   True

Чтобы посмотреть все строки DataFrame, которые НЕ СОДЕРЖАТ NA можно применить метод DataFrame.all():

>>> df.notna().all(axis=1)
# 0    False
# 1     True
# 2    False
# dtype: bool

Теперь, используя "логическую индексацию" выведем сами строки DataFrame:

>>> df.loc[df.notna().all(axis=1)]
#    age       born    name        toy
# 1  6.0 1939-05-27  Batman  Batmobile

Передавая отрицание ~ логической индексации, можно вывести строки, содержащие NA:

>>> df.loc[~df.notna().all(axis=1)]
#    age       born    name    toy
# 0  5.0        NaT  Alfred   None
# 2  NaN 1940-04-25          Joker

Перейдем к Series и покажем, какие записи НЕ являются NA.

>>> ser = pd.Series([5, 6, np.nan])
>>> ser
# 0    5.0
# 1    6.0
# 2    NaN
# dtype: float64

>>> ser.notna()
# 0     True
# 1     True
# 2    False
# dtype: bool

# применяем логическую индексацию
>>> ser[ser.notna()]
# 0    5.0
# 1    6.0
# dtype: float64

# теперь строки содержащие `NA`
>>> ser[~ser.notna()]
# 2   NaN
# dtype: float64

- DataFrame.isnull():
- Series.isnull():

Методы DataFrame.isnull() и Series.isnull() являются псевдонимами методов DataFrame.isna() и Series.isna().

- DataFrame.notnull():
- Series.notnull():

Методы DataFrame.notnull() и Series.notnull() являются псевдонимами методов DataFrame.notna() и Series.notna().

DataFrame.dropna(*, axis=0, how=no_default, thresh=no_default, subset=None, inplace=False, ignore_index=False):

Метод DataFrame.dropna() возвращает новый DataFrame с удаленными из него записями NA или None.

Принимаемые аргументы:

  • axis: будут ли удалены строки или столбцы, содержащие пропущенные значения. Допускается использование только одной оси.

    Принимает значения:

    • 0 или 'index': удаляет строки, содержащих пропущенные значения.
    • 1 или 'columns': удаляет столбцы, содержащих пропущенные значения.

  • how: удаляется ли строка или столбец из DataFrame, если у нас есть хотя бы один NA или все NA.

    Принимает значения:

    • 'any': если присутствуют какие-либо значения NA или None.
    • 'all': если все значения имеют значение NA или None.

  • thresh: какое количество значений, отличных от NA требуется удалить. Нельзя совмещать с аргументом how.

  • subset метки вдоль другой оси, которые следует учитывать. Например, если удаляются строки, это будет список столбцов, которые нужно включить. Принимает метку столбца или последовательность индексных меток.

  • inplace: следует ли изменять DataFrame вместо создания нового. Значение по умолчанию False.

  • ignore_index: Если значение True, то результирующая ось будет помечена как 0, 1, ..., n - 1. Значение по умолчанию False.

Примеры использования DataFrame.dropna():

>>> df = pd.DataFrame({"name": ['Alfred', 'Batman', 'Catwoman'],
...                    "toy": [np.nan, 'Batmobile', 'Bullwhip'],
...                    "born": [pd.NaT, pd.Timestamp("1940-04-25"),
...                             pd.NaT]})
>>> df
#        name        toy       born
# 0    Alfred        NaN        NaT
# 1    Batman  Batmobile 1940-04-25
# 2  Catwoman   Bullwhip        NaT

Удаляем строки, в которых отсутствует хотя бы один элемент.

>>> df.dropna()
#      name        toy       born
# 1  Batman  Batmobile 1940-04-25

Удаляем столбцы, в которых отсутствует хотя бы один элемент.

>>> df.dropna(axis='columns')
#        name
# 0    Alfred
# 1    Batman
# 2  Catwoman

Удаляем строки, в которых отсутствуют все элементы.

>>> df.dropna(how='all')
#        name        toy       born
# 0    Alfred        NaN        NaT
# 1    Batman  Batmobile 1940-04-25
# 2  Catwoman   Bullwhip        NaT

Оставляем только строки, содержащие как минимум два значения, отличные от NA.

>>> df.dropna(thresh=2)
#        name        toy       born
# 1    Batman  Batmobile 1940-04-25
# 2  Catwoman   Bullwhip        NaT

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

>>> df.dropna(subset=['name', 'toy'])
#        name        toy       born
# 1    Batman  Batmobile 1940-04-25
# 2  Catwoman   Bullwhip        NaT

Series.dropna(*, inplace=False, ignore_index=False):

Метод Series.dropna() возвращает новую Series с удаленными из нее записями NA или None.

Принимаемые аргументы:

  • inplace: следует ли изменять Series вместо создания новой. Значение по умолчанию False.
  • ignore_index: Если значение True, то результирующая ось будет помечена как 0, 1, ..., n - 1. Значение по умолчанию False.

Примеры использования Series.dropna():

>>> ser = pd.Series([1., 2., np.nan])
>>> ser
# 0    1.0
# 1    2.0
# 2    NaN
# dtype: float64

Удаляем значения NA из серии.

>>> ser.dropna()
# 0    1.0
# 1    2.0
# dtype: float64

Пустые строки не считаются значениями NA. None считается значением NA.

>>> ser = pd.Series([np.nan, 2, pd.NaT, '', None, 'I stay'])
>>> ser
# 0       NaN
# 1         2
# 2       NaT
# 3
# 4      None
# 5    I stay
# dtype: object

>>> ser.dropna()
# 1         2
# 3
# 5    I stay
# dtype: object

- DataFrame.fillna(value=None, *, axis=None, inplace=False, limit=None, downcast=no_default):
- Series.fillna(value=None, *, inplace=False, limit=None, downcast=no_default):

Методы DataFrame.fillna() и Series.fillna() заполняют значение None/NA/NaN значением, переданным в value в DataFrame и Series соответственно..

Принимаемые аргументы:

  • value: значение, используемое для заполнения (например, 0), либо dict/Series/DataFrame значений, определяющих, какое значение использовать для каждого индекса (для Series) или столбца (для DataFrame). Значения, отсутствующие в dict/Series/DataFrame, не будут заполнены. Значение value не может быть списком.
  • axis: ось, по которой заполняются недостающие значения. Для Series этот аргумент не используется и по умолчанию равен 0. Для DataFrame может принимать значения: 0 или 'index', 1 или 'columns'.
  • inplace: если True, изменяет DataFrame/Series на месте. Примечание: это приведет к изменению любых других представлений этого объекта (например, фрагмента без копирования для столбца в DataFrame).
  • limit: это максимальное количество записей по всей оси axis, где будут заполнены NaN. Должно быть больше 0, если не None.
  • downcast: принимает словарь {item:dtype, ...} - того, что нужно понизить в размерности, если это возможно, или строку 'infer', которая попытается привести к соответствующему равному типу (например, float64 в int64, если это возможно).

Примеры использования DataFrame.fillna():

>>> df = pd.DataFrame([[np.nan, 2, np.nan, 0],
...                    [3, 4, np.nan, 1],
...                    [np.nan, np.nan, np.nan, np.nan],
...                    [np.nan, 3, np.nan, 4]],
...                   columns=list("ABCD"))
>>> df
#      A    B   C    D
# 0  NaN  2.0 NaN  0.0
# 1  3.0  4.0 NaN  1.0
# 2  NaN  NaN NaN  NaN
# 3  NaN  3.0 NaN  4.0

Заменяем все элементы NaN на 0.

>>> df.fillna(0)
#      A    B    C    D
# 0  0.0  2.0  0.0  0.0
# 1  3.0  4.0  0.0  1.0
# 2  0.0  0.0  0.0  0.0
# 3  0.0  3.0  0.0  4.0

Заменяем все элементы NaN в столбцах 'A', 'B', 'C' и 'D' на 0, 1, 2 и 3 соответственно.

>>> values = {"A": 0, "B": 1, "C": 2, "D": 3}
>>> df.fillna(value=values)
#      A    B    C    D
# 0  0.0  2.0  2.0  0.0
# 1  3.0  4.0  2.0  1.0
# 2  0.0  1.0  2.0  3.0
# 3  0.0  3.0  2.0  4.0

Заменяем только первый элемент NaN.

>>> df.fillna(value=values, limit=1)
#      A    B    C    D
# 0  0.0  2.0  2.0  0.0
# 1  3.0  4.0  NaN  1.0
# 2  NaN  1.0  NaN  3.0
# 3  NaN  3.0  NaN  4.0

При заполнении с помощью DataFrame замена происходит по тем же именам столбцов и тем же индексам:

>>> df2 = pd.DataFrame(np.zeros((4, 4)), columns=list("ABCE"))
>>> df.fillna(df2)
#      A    B    C    D
# 0  0.0  2.0  0.0  0.0
# 1  3.0  4.0  0.0  1.0
# 2  0.0  0.0  0.0  NaN
# 3  0.0  3.0  0.0  4.0

Обратите внимание, что столбец 'D' не затрагивается, так как он отсутствует в df2.