Значение NaN
Константа NaN (Not a Number) в библиотеке Pandas используется
для обозначения пропущенных, отсутствующих или неопределённых
числовых данных. Она является частью стандарта IEEE 754 для
представления чисел с плавающей запятой и используется в Pandas
как основной маркер для пропусков в числовых столбцах.
Важно понимать, что NaN - это не строка и не нулевое значение,
а специальное состояние, которое говорит о том, что данные
неизвестны или не могут быть вычислены. Это отличает его от
None в Python, который чаще используется для объектов
и строк, хотя Pandas преобразует None в NaN
в числовых колонках для единообразия.
Главная особенность NaN заключается в том, что любое
арифметическое действие с его участием возвращает NaN,
а стандартные операции сравнения (например, nan == nan)
возвращают False. Именно поэтому для проверки на
наличие пропусков в Pandas существуют специальные методы,
а не прямое сравнение.
Создание NaN
Константу NaN можно получить несколькими способами:
импортировать из модуля math или numpy, либо
она автоматически появляется при создании данных с пропусками.
Рассмотрим основные способы:
import pandas as pd
import numpy as np
import math
# Способ 1 - через numpy
nan_np = np.nan
# Способ 2 - через math
nan_math = math.nan
# Способ 3 - автоматически при создании Series
ser = pd.Series([1, 2, None, 4, 5])
print(nan_np)
print(nan_math)
print(ser)
Результат выполнения кода:
nan
nan
0 1.0
1 2.0
2 NaN
3 4.0
4 5.0
dtype: float64
Особенности сравнения
Как уже упоминалось, сравнение NaN с самим собой даёт
ложь. Это приводит к неожиданным результатам, если не знать
об этой особенности:
import pandas as pd
import numpy as np
nan = np.nan
print(nan == nan)
print(nan is nan)
print(nan == 0)
print(nan > 5)
Результат выполнения кода:
False
True
False
False
Обратите внимание, что оператор is работает иначе,
но его использование для проверки на пропуски не рекомендуется,
так как внутри Pandas используются разные объекты NaN.
Для проверки следует использовать специальные методы.
Арифметика с NaN
Любое математическое действие с участием NaN всегда
возвращает NaN. Это важно учитывать при расчётах:
import pandas as pd
import numpy as np
a = np.nan
print(a + 10)
print(a * 2)
print(a / 3)
print(a ** 0)
Результат выполнения кода:
nan
nan
nan
nan
Исключением является случай возведения в нулевую степень,
но в Pandas с NaN это тоже вернёт NaN.
Проверка на NaN
Как было сказано ранее, прямое сравнение не подходит для
проверки на наличие пропусков. Вместо этого следует
использовать методы isna или isnull,
а также их отрицания notna и notnull:
import pandas as pd
import numpy as np
ser = pd.Series([1, 2, np.nan, 4, 5])
print(ser.isna())
print(ser.isnull())
print(ser.notna())
Результат выполнения кода:
0 False
1 False
2 True
3 False
4 False
dtype: bool
0 False
1 False
2 True
3 False
4 False
dtype: bool
0 True
1 True
2 False
3 True
4 True
dtype: bool
Работа с агрегациями
При вычислении статистических показателей методом mean,
sum и другими, пропуски по умолчанию игнорируются.
Однако, если все значения в столбце равны NaN,
результатом будет NaN:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'a': [1, 2, 3, 4, 5],
'b': [np.nan, np.nan, np.nan, np.nan, np.nan]
})
print(df.mean())
print(df['b'].sum())
print(df['b'].mean())
Результат выполнения кода:
a 3.0
b NaN
dtype: float64
0.0
nan
Проверка наличия NaN в данных
Для проверки, есть ли в таблице или серии хотя бы один
пропуск, можно использовать методы isna и any
в комбинации:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'a': [1, 2, 3, 4, 5],
'b': [10, np.nan, 30, 40, 50]
})
print(df.isna().any().any())
print(df['b'].isna().any())
print(df['a'].isna().any())
Результат выполнения кода:
True
True
False