From f216c74d0b250d4079278cdef7bce43be76d0504 Mon Sep 17 00:00:00 2001 From: George Kuan Date: Fri, 3 Jan 2014 14:31:45 -0800 Subject: [PATCH] BUG/TST: Fixes isnull behavior on NaT in array. Closes #5443 common._isnull_ndarraylike(...) uses lib.isnullobj to check nulls/NaN/NaT in ndarray, which in turn relies on util._checknull. _checknull did not know about NaT, but now lib.isnullobj does, while still maintaining performance by doing arr[i] only once. Added a test case test_isnull_nat() to test_common.py and check for NaT in lib.isnullobj. pd.isnull(np.array([pd.NaT])) now yields the correct results ([True]). --- pandas/lib.pyx | 6 +++--- pandas/src/util.pxd | 2 +- pandas/tests/test_common.py | 10 +++++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pandas/lib.pyx b/pandas/lib.pyx index 56ef9a4fcb160..afd8ac87589be 100644 --- a/pandas/lib.pyx +++ b/pandas/lib.pyx @@ -170,7 +170,6 @@ cdef inline int64_t get_timedelta64_value(val): cdef double INF = np.inf cdef double NEGINF = -INF - cpdef checknull(object val): if util.is_float_object(val) or util.is_complex_object(val): return val != val # and val != INF and val != NEGINF @@ -183,7 +182,7 @@ cpdef checknull(object val): elif is_array(val): return False else: - return util._checknull(val) + return _checknull(val) cpdef checknull_old(object val): if util.is_float_object(val) or util.is_complex_object(val): @@ -213,7 +212,8 @@ def isnullobj(ndarray[object] arr): n = len(arr) result = np.zeros(n, dtype=np.uint8) for i from 0 <= i < n: - result[i] = util._checknull(arr[i]) + arobj = arr[i] + result[i] = arobj is NaT or _checknull(arobj) return result.view(np.bool_) @cython.wraparound(False) diff --git a/pandas/src/util.pxd b/pandas/src/util.pxd index 7a30f018e623e..d6f3c4caea306 100644 --- a/pandas/src/util.pxd +++ b/pandas/src/util.pxd @@ -67,7 +67,7 @@ cdef inline is_array(object o): cdef inline bint _checknull(object val): try: - return val is None or (cpython.PyFloat_Check(val) and val != val) + return val is None or (cpython.PyFloat_Check(val) and val != val) except ValueError: return False diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index 7b4ea855f2f9d..9be485b143d5f 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -5,7 +5,7 @@ import nose from nose.tools import assert_equal import numpy as np -from pandas.tslib import iNaT +from pandas.tslib import iNaT, NaT from pandas import Series, DataFrame, date_range, DatetimeIndex, Timestamp from pandas import compat @@ -114,6 +114,14 @@ def test_isnull_lists(): result = isnull([u('foo'), u('bar')]) assert(not result.any()) +def test_isnull_nat(): + result = isnull([NaT]) + exp = np.array([True]) + assert(np.array_equal(result, exp)) + + result = isnull(np.array([NaT], dtype=object)) + exp = np.array([True]) + assert(np.array_equal(result, exp)) def test_isnull_datetime(): assert (not isnull(datetime.now()))