Numpy: проверка значения NaT
nat = np.datetime64('NaT')
nat == nat
>> FutureWarning: In the future, 'NAT == x' and 'x == NAT' will always be False.
np.isnan(nat)
>> TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Как я могу проверить, является ли datetime64 NaT? Я не могу ничего выудить из документов. Я знаю, что панды могут это сделать, но я бы предпочел не добавлять зависимость для чего-то настолько основного.
6 ответов
введение: этот ответ был написан в то время, когда Numpy была версией 1.11, и поведение сравнения NAT должно было измениться с версии 1.12. Ясно, что это не так и вторая часть ответа не получилось. Первая часть ответа может быть неприменима для новых версий numpy. Убедитесь, что вы проверили ответы MSeifert ниже.
Когда вы делаете сравнение в первый раз, у вас всегда есть предупреждение. Но тем временем вернулся результат сравнение правильное:
import numpy as np
nat = np.datetime64('NaT')
def nat_check(nat):
return nat == np.datetime64('NaT')
nat_check(nat)
Out[4]: FutureWarning: In the future, 'NAT == x' and 'x == NAT' will always be False.
True
nat_check(nat)
Out[5]: True
если вы хотите подавить предупреждения, вы можете использовать catch_warnings контекст-менеджера:
import numpy as np
import warnings
nat = np.datetime64('NaT')
def nat_check(nat):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return nat == np.datetime64('NaT')
nat_check(nat)
Out[5]: True
EDIT: почему-то поведение сравнения NAT в Numpy версии 1.12 не изменилось, поэтому следующий код оказался непоследовательным.
и, наконец, вы можете проверить версию numpy для обработки измененного поведения с версии 1.12.0:
def nat_check(nat):
if [int(x) for x in np.__version__.split('.')[:-1]] > [1, 11]:
return nat != nat
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return nat == np.datetime64('NaT')
EDIT: As MSeifert упомянуто, Numpy содержит
isnat
функция с версии 1.13.панды можно проверить на NaT
С pandas.isnull
:
>>> import numpy as np
>>> import pandas as pd
>>> pd.isnull(np.datetime64('NaT'))
True
если вы не хотите использовать панды, вы также можете определить свою собственную функцию (части взяты из источника панды):
nat_as_integer = np.datetime64('NAT').view('i8')
def isnat(your_datetime):
dtype_string = str(your_datetime.dtype)
if 'datetime64' in dtype_string or 'timedelta64' in dtype_string:
return your_datetime.view('i8') == nat_as_integer
return False # it can't be a NaT if it's not a dateime
это правильно определяет значения NaT:
>>> isnat(np.datetime64('NAT'))
True
>>> isnat(np.timedelta64('NAT'))
True
и понимает, если это не datetime или timedelta:
>>> isnat(np.timedelta64('NAT').view('i8'))
False
в будущем может быть isnat
-функция в коде numpy, по крайней мере, у них есть a (в настоящее время открыт) запрос pull об этом:ссылка на PR (NumPy github)
Так как NumPy версии 1.13 он содержит isnat
функция:
>>> import numpy as np
>>> np.isnat(np.datetime64('nat'))
True
Он также работает для массивов:
>>> np.isnat(np.array(['nat', 1, 2, 3, 4, 'nat', 5], dtype='datetime64[D]'))
array([ True, False, False, False, False, True, False], dtype=bool)
очень просто и удивительно быстро: (без numpy или панд)
str( myDate ) == 'NaT' # True if myDate is NaT
хорошо, это немного неприятно, но, учитывая двусмысленность вокруг "NaT", это делает работу хорошо.
это также полезно при сравнении двух дат, каждая из которых может быть NaT следующим образом:
str( date1 ) == str( date1 ) # True
str( date1 ) == str( NaT ) # False
str( NaT ) == str( date1 ) # False
wait for it...
str( NaT ) == str( Nat ) # True (hooray!)
этот подход позволяет избежать предупреждений при сохранении оценки, ориентированной на массив.
import numpy as np
def isnat(x):
"""
datetime64 analog to isnan.
doesn't yet exist in numpy - other ways give warnings
and are likely to change.
"""
return x.astype('i8') == np.datetime64('NaT').astype('i8')
другим способом было бы поймать exeption:
def is_nat(npdatetime):
try:
npdatetime.strftime('%x')
return False
except:
return True