В предыдущих разделах вы видели, как легко могут образовываться недостающие данные. В структурах они определяются как значения NaN
(Not a Value). Такой тип довольно распространен в анализе данных.
Но pandas спроектирован так, чтобы лучше с ними работать. Дальше вы узнаете, как взаимодействовать с NaN
, чтобы избегать возможных проблем. Например, в библиотеке pandas вычисление описательной статистики неявно исключает все значения NaN
.
Присваивание значения NaN
Если нужно специально присвоить значение NaN
элементу структуры данных, для этого используется np.NaN
(или np.nan
) из библиотеки NumPy.
>>> ser = pd.Series([0,1,2,np.NaN,9],
... index=['red','blue','yellow','white','green'])
>>> ser
red 0.0
blue 1.0
yellow 2.0
white NaN
green 9.0
dtype: float64
>>> ser['white'] = None
>>> ser
red 0.0
blue 1.0
yellow 2.0
white NaN
green 9.0
dtype: float64
Фильтрование значений NaN
Есть несколько способов, как можно избавиться от значений NaN
во время анализа данных. Это можно делать вручную, удаляя каждый элемент, но такая операция сложная и опасная, к тому же не гарантирует, что вы действительно избавились от всех таких значений. Здесь на помощь приходит функция dropna()
.
>>> ser.dropna()
red 0.0
blue 1.0
yellow 2.0
green 9.0
dtype: float64
Функцию фильтрации можно выполнить и прямо с помощью notnull()
при выборе элементов.
>>> ser[ser.notnull()]
red 0.0
blue 1.0
yellow 2.0
green 9.0
dtype: float64
В случае с Dataframe
это чуть сложнее. Если использовать функцию pandas dropna()
на таком типе объекта, который содержит всего одно значение NaN
в колонке или строке, то оно будет удалено.
>>> frame3 = pd.DataFrame([[6,np.nan,6],[np.nan,np.nan,np.nan],[2,np.nan,5]],
... index = ['blue','green','red'],
... columns = ['ball','mug','pen'])
>>> frame3
ball | mug | pen | |
---|---|---|---|
blue | 6.0 | NaN | 6.0 |
green | NaN | NaN | NaN |
red | 2.0 | NaN | 5.0 |
>>> frame3.dropna()
Empty DataFrame
Columns: [ball, mug, pen]
Index: []
Таким образом чтобы избежать удаления целых строк или колонок нужно использовать параметр how
, присвоив ему значение all
. Это сообщит функции, чтобы она удаляла только строки или колонки, где все элементы равны NaN
.
>>> frame3.dropna(how='all')
ball | mug | pen | |
---|---|---|---|
blue | 6.0 | NaN | 6.0 |
red | 2.0 | NaN | 5.0 |
Заполнение NaN
Вместо того чтобы отфильтровывать значения NaN
в структурах данных, рискуя удалить вместе с ними важные элементы, можно заменять их на другие числа. Для этих целей подойдет fillna()
. Она принимает один аргумент — значение, которым нужно заменить NaN
.
>>> frame3.fillna(0)
ball | mug | pen | |
---|---|---|---|
blue | 6.0 | 0.0 | 6.0 |
green | 0.0 | 0.0 | 0.0 |
red | 2.0 | 0.0 | 5.0 |
Или же NaN
можно заменить на разные значения в зависимости от колонки, указывая их и соответствующие значения.
>>> frame3.fillna({'ball':1,'mug':0,'pen':99})
ball | mug | pen | |
---|---|---|---|
blue | 6.0 | 0.0 | 6.0 |
green | 1.0 | 0.0 | 99.0 |
red | 2.0 | 0.0 | 5.0 |