Нашли ошибку?
среднийpandas 3.0.6

Пропуски

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

Нужно знать:Первичный осмотрФильтрация строк

Содержание статьи

Коротко

  • Пропуск в числах и строках — NaN; в nullable-типах (Int64, boolean, string) — pd.NA. None при создании превращается в одно из них.
  • isna() / notna() — маски; isna().sum() — сколько пропусков в каждом столбце.
  • fillna(значение) — заполнить; словарь — своё значение для каждого столбца. ffill() / bfill() — предыдущим / следующим значением.
  • dropna() удаляет строки с пропусками; subset — смотреть только на эти столбцы, thresh — сколько непустых значений нужно, чтобы оставить строку.
  • interpolate() — восстановить значения между известными (линейно, по времени и т. д.).

Синтаксис

df.isna(), df.notna(), df.isna().sum()
df.fillna(value)                  # число или {"col": value}
df.ffill(), df.bfill()
df.dropna(how="any", subset=None, thresh=None, axis=0)
s.interpolate(method="linear")

Параметры

ПараметрЧто делаетПо умолчанию
valueв fillna: значение, словарь по столбцам или Seriesобязательный
howв dropna: "any" — удалить при любом пропуске, "all" — только если пропущено всё"any"
subsetв dropna: какие столбцы проверятьвсе
threshв dropna: минимальное число непустых значений в строкеNone
axis0 — строки, 1 — столбцы (в ffill — заполнять вдоль строки)0
limitв fillna / ffill / interpolate: сколько подряд пропусков заполнятьNone
methodв interpolate: "linear", "time", "nearest", "polynomial"…"linear"

Примеры

Данные для примеровиспользуются во всех примерах ниже
temps = pd.DataFrame({
    "city": ["Омск", "Тула", "Сочи", None],
    "mon": [12.0, None, 21.0, 8.0],
    "tue": [None, None, 22.5, 9.5],
})
Найти пропуски
print(temps.isna())
temps.isna().sum()                       # пропуски по столбцам
Вывод
    city    mon    tue
0  False  False   True
1  False   True   True
2  False  False  False
3   True  False  False
city    1
mon     1
tue     2
dtype: int64
Заполнить значением
print(temps.fillna({"city": "?", "mon": 0}))   # по столбцам
temps["mon"].fillna(temps["mon"].mean())       # средним
Вывод
   city   mon   tue
0  Омск  12.0   NaN
1  Тула   0.0   NaN
2  Сочи  21.0  22.5
3     ?   8.0   9.5
0    12.000000
1    13.666667
2    21.000000
3     8.000000
Name: mon, dtype: float64
Заполнить предыдущим значением
temps[["mon", "tue"]].ffill(axis=1)       # предыдущим значением в строке
Вывод
    mon   tue
0  12.0  12.0
1   NaN   NaN
2  21.0  22.5
3   8.0   9.5
Удалить строки с пропусками
print(temps.dropna())                    # строки без единого пропуска
print(temps.dropna(subset=["city"]))     # пропуск только в city
temps.dropna(thresh=2)                   # хотя бы 2 непустых значения
Вывод
   city   mon   tue
2  Сочи  21.0  22.5
   city   mon   tue
0  Омск  12.0   NaN
1  Тула   NaN   NaN
2  Сочи  21.0  22.5
   city   mon   tue
0  Омск  12.0   NaN
2  Сочи  21.0  22.5
3   NaN   8.0   9.5
Интерполяция
s = pd.Series([10.0, None, None, 16.0, None, 20.0])
s.interpolate()                          # линейно между соседями
Вывод
0    10.0
1    12.0
2    14.0
3    16.0
4    18.0
5    20.0
dtype: float64
Во что превращается None
print(pd.Series([1, None]).dtype)        # число + None → float64 с NaN
print(pd.Series(["a", None]).dtype)      # строка + None → str с NaN
pd.Series([1, None], dtype="Int64")      # целые с пропуском — pd.NA
Вывод
float64
str
0       1
1    <NA>
dtype: Int64

Подводные камни

Сравнение с np.nan

== np.nan
temps["mon"] == np.nan                   # так пропуски не найти
Вывод
0    False
1    False
2    False
3    False
Name: mon, dtype: bool

Проверяйте пропуски только через isna().

fillna(method=…) удалён

fillna с methodошибка: TypeError
temps["mon"].fillna(method="ffill")
Ошибка
TypeError: NDFrame.fillna() got an unexpected keyword argument 'method'