Значение NaT
Значение NaT (Not a Time) используется в Pandas для обозначения
отсутствующих или некорректных значений в данных типа даты и времени.
Это аналог NaN для числовых данных, но специально предназначенный
для datetime64, timedelta64 и Period.
При работе с временными рядами NaT появляется при конвертации
невалидных строк в даты, при объединении таблиц с несовпадающими
индексами или при операциях с пропущенными временными метками.
Важно понимать, что NaT сравнивается с другими значениями
особым образом: любое сравнение с NaT возвращает False,
кроме сравнения на isna и isnull.
Создание и основные свойства
Рассмотрим, как создаются значения NaT и как их идентифицировать:
import pandas as pd
import numpy as np
# Создание через явное указание
ser1 = pd.Series([pd.NaT, '2024-01-01', '2024-01-02'])
print(ser1)
print("\nТип данных:", ser1.dtype)
print("Является ли первый элемент NaT:", pd.isna(ser1[0]))
Результат выполнения кода:
0 NaT
1 2024-01-01
2 2024-01-02
dtype: datetime64[ns]
Тип данных: datetime64[ns]
Является ли первый элемент NaT: True
Также NaT автоматически появляется при неудачном парсинге дат:
import pandas as pd
# При конвертации некорректных строк
dates = ['2024-01-01', 'invalid', '2024-01-03']
ser = pd.to_datetime(dates, errors='coerce')
print(ser)
Результат выполнения кода:
0 2024-01-01
1 NaT
2 2024-01-03
dtype: datetime64[ns]
Проверка на NaT
Для проверки значений на NaT используются методы isna
и isnull. Обычное сравнение через операторы не работает:
import pandas as pd
ser = pd.Series([pd.NaT, '2024-01-01', '2024-01-02'])
# Правильный способ проверки
print("isna:", ser.isna())
print("\nisnull:", ser.isnull())
# Неправильный способ - сравнение с NaT
print("\nser == pd.NaT:", ser == pd.NaT)
Результат выполнения кода:
isna: 0 True
1 False
2 False
dtype: bool
isnull: 0 True
1 False
2 False
dtype: bool
ser == pd.NaT: 0 False
1 False
2 False
dtype: bool
Фильтрация данных с NaT
Значения NaT можно отфильтровать с помощью метода notna
или dropna:
import pandas as pd
ser = pd.Series([pd.NaT, '2024-01-01', pd.NaT, '2024-01-02'])
print("Исходная серия:")
print(ser)
# Фильтрация с помощью булевого индексирования
filtered = ser[ser.notna()]
print("\nОтфильтрованная серия:")
print(filtered)
# Фильтрация с помощью dropna
ser_dropped = ser.dropna()
print("\nПосле dropna:")
print(ser_dropped)
Результат выполнения кода:
Исходная серия:
0 NaT
1 2024-01-01
2 NaT
3 2024-01-02
dtype: datetime64[ns]
Отфильтрованная серия:
1 2024-01-01
3 2024-01-02
dtype: datetime64[ns]
После dropna:
1 2024-01-01
3 2024-01-02
dtype: datetime64[ns]
NaT в DataFrame
В таблицах NaT обрабатывается аналогично сериям. Посмотрим,
как это работает в DataFrame:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'a': [1, 2, 3, 4],
'b': [pd.NaT, '2024-01-01', pd.NaT, '2024-01-02']
})
print("Исходная таблица:")
print(df)
# Подсчёт количества NaT в столбце
print("\nКоличество NaT в столбце 'b':")
print(df['b'].isna().sum())
# Удаление строк с NaT
df_clean = df.dropna()
print("\nТаблица после удаления строк с NaT:")
print(df_clean)
Результат выполнения кода:
Исходная таблица:
a b
0 1 NaT
1 2 2024-01-01
2 3 NaT
3 4 2024-01-02
Количество NaT в столбце 'b':
2
Таблица после удаления строк с NaT:
a b
1 2 2024-01-01
3 4 2024-01-02
Агрегация и NaT
Значения NaT игнорируются в большинстве агрегирующих функций,
таких как mean или min:
import pandas as pd
ser = pd.Series([
pd.NaT,
'2024-01-01',
'2024-01-02',
'2024-01-03'
])
print("Минимальная дата:", ser.min())
print("Максимальная дата:", ser.max())
print("Количество значений:", ser.count())
Результат выполнения кода:
Минимальная дата: 2024-01-01
Максимальная дата: 2024-01-03
Количество значений: 3
Заполнение NaT
Значения NaT можно заменить с помощью метода fillna,
передавая конкретную дату или другой способ заполнения:
import pandas as pd
ser = pd.Series([pd.NaT, '2024-01-01', pd.NaT, '2024-01-03'])
print("Исходная серия:")
print(ser)
# Заполнение конкретной датой
filled = ser.fillna('2024-01-02')
print("\nЗаполненная серия:")
print(filled)
# Заполнение методом forward fill
ffilled = ser.fillna(method='ffill')
print("\nЗаполнение предыдущим значением:")
print(ffilled)
Результат выполнения кода:
Исходная серия:
0 NaT
1 2024-01-01
2 NaT
3 2024-01-03
dtype: datetime64[ns]
Заполненная серия:
0 2024-01-02
1 2024-01-01
2 2024-01-02
3 2024-01-03
dtype: datetime64[ns]
Заполнение предыдущим значением:
0 NaT
1 2024-01-01
2 2024-01-01
3 2024-01-03
dtype: datetime64[ns]