Отсутствующие значения распространены и возникают либо из-за человеческой ошибки, ошибки прибора, обработки другой командой, либо просто из-за отсутствия данных для определенного наблюдения.
В этом байте мы рассмотрим, как заполнить NaN в
DataFrame
, если вы решите обрабатывать NaN, заполняя их.
Во-первых, давайте создадим макет DataFrame
с некоторыми выпавшими случайными значениями:
import numpy as np
array = np.random.randn(25, 3)
mask = np.random.choice([1, 0], array.shape, p=[.3, .7]).astype(bool)
array[mask] = np.nan
df = pd.DataFrame(array, columns=['Col1', 'Col2', 'Col3'])
Col1 Col2 Col3
0 -0.671603 -0.792415 0.783922
1 0.207720 NaN 0.996131
2 -0.892115 -1.282333 NaN
3 -0.315598 -2.371529 -1.959646
4 NaN NaN -0.584636
5 0.314736 -0.692732 -0.303951
6 0.355121 NaN NaN
7 NaN -1.900148 1.230828
8 -1.795468 0.490953 NaN
9 -0.678491 -0.087815 NaN
10 0.755714 0.550589 -0.702019
11 0.951908 -0.529933 0.344544
12 NaN 0.075340 -0.187669
13 NaN 0.314342 -0.936066
14 NaN 1.293355 0.098964
Построим, скажем, третий столбец:
plt.plot(df['Col3'])
При заполнении различными методами этот заполненный NaN график можно заменить на:
fillna () — среднее, медиана, мода
Вы можете ввести эти значения в новый столбец и назначить его столбцу, который вы хотите заполнить, или на месте с помощью inplace
аргумент. Здесь мы будем извлекать заполненные значения в новый столбец для простоты проверки:
mean = df['Col3'].fillna(df['Col3'].mean(), inplace=False)
median = df['Col3'].fillna(df['Col3'].median(), inplace=False)
mode = df['Col3'].fillna(df['Col3'].mode(), inplace=False)
Медиана, среднее значение и мода столбца -0.187669
, -0.110873
и 0.000000
и эти значения будут использоваться для каждого NaN соответственно. Это эффективное заполнение постоянными значениями, где вводимое значение зависит от содержимого столбца.
Во-первых, заполнение медианными значениями приводит к:
Со средними значениями:
Со значениями режима:
fillna () — постоянное значение
Вместо этого вы также можете заполнить постоянное значение:
Ознакомьтесь с нашим практическим руководством по изучению Git с рекомендациями, принятыми в отрасли стандартами и прилагаемой памяткой. Перестаньте гуглить команды Git и на самом деле изучить это!
constant = df['Col3'].fillna(0, inplace=False
Это приводит к тому, что вместо каждого NaN ставится постоянное значение (0). 0
близок к нашей медиане, среднему значению и равен моде, поэтому заполненные значения будут очень похожи на этот метод для нашего фиктивного набора данных:
0 0.783922
1 0.996131
2 0.000000
3 -1.959646
4 -0.584636
5 -0.303951
6 0.000000
7 1.230828
8 0.000000
9 0.000000
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
fillna () — заполнение вперед и назад
В каждой строке — вы можете выполнить прямое или обратное заполнение, взяв значение из строки до или после:
ffill = df['Col3'].fillna(method='ffill')
bfill = df['Col3'].fillna(method='bfill')
При прямом заполнении, поскольку нам не хватает строки 2, для заполнения второй строки берется значение из строки 1. Значения распространяются вперед:
0 0.783922
1 0.996131
2 0.996131
3 -1.959646
4 -0.584636
5 -0.303951
6 -0.303951
7 1.230828
8 1.230828
9 1.230828
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
При обратном заполнении происходит обратное. Строка 2 заполняется значением из строки 3:
0 0.783922
1 0.996131
2 -1.959646
3 -1.959646
4 -0.584636
5 -0.303951
6 1.230828
7 1.230828
8 -0.702019
9 -0.702019
10 -0.702019
11 0.344544
12 -0.187669
13 -0.936066
14 0.098964
Хотя, если их больше одного NaN
в последовательности — это не будет хорошо и может каскадировать NaN дальше вниз, искажая данные и удаляя фактически записанные значения.
интерполировать ()
Ассоциация interpolate()
метод делегирует интерполяцию значений методу SciPy. набор методов для интерполяции значений. Он принимает широкий спектр аргументов, в том числе, nearest
, zero
, slinear
, quadratic
, cubic
, spline
, barycentric
, polynomial
, krogh
, piecewise_polynomial
, spline
, pchip
, akima
, cubicspline
, и т.д.
Интерполяция гораздо более гибкая и «умная», чем простое заполнение значений константами или полупеременными, как в предыдущих методах.
Интерполяция может правильно заполнить последовательность так, как не могут другие методы, например:
s = pd.Series([0, 1, np.nan, np.nan, np.nan, 5])
s.fillna(s.mean()).values
s.fillna(method='ffill').values
s.interpolate().values
Интерполяция по умолчанию является линейной, и если предположить, что 1...5
скорее всего 1, 2, 3, 4, 5
последовательность не надуманная (но не гарантируется). Как постоянное заполнение, так и прямое или обратное заполнение здесь с треском терпят неудачу. Вообще говоря, интерполяция обычно будет хорошим другом, когда дело доходит до заполнения NaN зашумленными сигналами или поврежденными наборами данных.
Экспериментирование с типами интерполяции может дать лучшие результаты.
Вот два метода интерполяции (splice
и polynomial
требовать order
аргумент):
nearest = df['Col3'].interpolate(method='nearest')
polynomial = df['Col3'].interpolate(method='polynomial', order=3)
Это приводит к:
А также: