Подтвердить что ты не робот

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? Я не могу что-то вырыть из документов. Я знаю, что Pandas может это сделать, но я бы предпочел не добавлять зависимость для чего-то такого базового.

4b9b3361

Ответ 1

INTRO: этот ответ был написан в то время, когда 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: Как упоминал MSeifert, Numpy содержит функцию isnat начиная с версии 1.13.

Ответ 2

можно проверить на NaT с pandas.isnull:

>>> import numpy as np
>>> import pandas as pd
>>> pd.isnull(np.datetime64('NaT'))
True

Если вы не хотите использовать pandas, вы также можете определить свою собственную функцию (части взяты из источника pandas):

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 not a dateime

Это правильно идентифицирует значения NaT:

>>> isnat(np.datetime64('NAT'))
True

>>> isnat(np.timedelta64('NAT'))
True

И понимает, если это не дата или timedelta:

>>> isnat(np.timedelta64('NAT').view('i8'))
False

В будущем в коде numpy может быть isnat -функция, по крайней мере у них есть (в настоящее время открытый) запрос на растяжение: Ссылка к PR (NumPy github)

Ответ 3

Поскольку версия 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)

Ответ 4

Очень просто и удивительно быстро: (без пупка или пупка)

    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!)

Ответ 5

Этот подход позволяет избежать предупреждений при сохранении массивно-ориентированной оценки.

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')

Ответ 6

Другой способ - поймать выход:

def is_nat(npdatetime):
    try:
        npdatetime.strftime('%x')
        return False
    except:
        return True