From 436f91cd8f6746cf004358045175ba67ef98e190 Mon Sep 17 00:00:00 2001 From: sinhrks Date: Sun, 22 Jun 2014 07:59:37 +0900 Subject: [PATCH] BUG: isnull doesnt handle PeriodNaT properly --- pandas/core/common.py | 5 +++-- pandas/lib.pyx | 6 +++++- pandas/tests/test_common.py | 37 +++++++++++++++++++++++++++++++++++++ vb_suite/panel_methods.py | 4 ++-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/pandas/core/common.py b/pandas/core/common.py index f8f5928ca7d51..7ce5fdb1392b7 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -221,6 +221,8 @@ def _isnull_new(obj): return obj._constructor(obj._data.isnull(func=isnull)) elif isinstance(obj, list) or hasattr(obj, '__array__'): return _isnull_ndarraylike(np.asarray(obj)) + elif isinstance(obj, pd.Period): + return obj.ordinal == tslib.iNaT else: return obj is None @@ -291,7 +293,6 @@ def _isnull_ndarraylike(obj): values = values.values result = values.isnull() else: - # Working around NumPy ticket 1542 shape = values.shape @@ -302,7 +303,7 @@ def _isnull_ndarraylike(obj): vec = lib.isnullobj(values.ravel()) result[...] = vec.reshape(shape) - elif is_datetimelike(obj): + elif dtype in _DATELIKE_DTYPES or isinstance(obj, pd.PeriodIndex): # this is the NaT pattern result = values.view('i8') == tslib.iNaT else: diff --git a/pandas/lib.pyx b/pandas/lib.pyx index 71aeaf0895035..33b7085116f26 100644 --- a/pandas/lib.pyx +++ b/pandas/lib.pyx @@ -218,6 +218,8 @@ cpdef checknull(object val): return get_timedelta64_value(val) == NPY_NAT elif is_array(val): return False + # elif is_periodnat(val): + # return True else: return _checknull(val) @@ -278,6 +280,8 @@ def item_from_zerodim(object val): """ return util.unbox_if_zerodim(val) +cdef is_periodnat(object val): + return hasattr(val, 'freq') and getattr(val, 'ordinal', None) == iNaT @cython.wraparound(False) @cython.boundscheck(False) @@ -290,7 +294,7 @@ def isnullobj(ndarray[object] arr): result = np.zeros(n, dtype=np.uint8) for i from 0 <= i < n: val = arr[i] - result[i] = val is NaT or _checknull(val) + result[i] = val is NaT or _checknull(val) or is_periodnat(val) return result.view(np.bool_) @cython.wraparound(False) diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index 36d6c39586d97..bb0dd12404f26 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -7,6 +7,7 @@ import nose from nose.tools import assert_equal import numpy as np +import pandas as pd from pandas.tslib import iNaT, NaT from pandas import Series, DataFrame, date_range, DatetimeIndex, Timestamp, Float64Index from pandas import compat @@ -143,6 +144,18 @@ def test_isnull_nat(): exp = np.array([True]) assert(np.array_equal(result, exp)) + result = isnull(pd.Period('NaT', freq='M')) + assert(result) + result = isnull([pd.Period('NaT', freq='M')]) + exp = np.array([True]) + assert(np.array_equal(result, exp)) + + result = notnull(pd.Period('NaT', freq='M')) + assert(not result) + result = notnull([pd.Period('NaT', freq='M')]) + exp = np.array([False]) + assert(np.array_equal(result, exp)) + def test_isnull_datetime(): assert (not isnull(datetime.now())) assert notnull(datetime.now()) @@ -166,6 +179,30 @@ def test_isnull_datetime(): mask = isnull(pidx[1:]) assert(not mask.any()) +def test_isnull_period(): + assert (not isnull(pd.Period('2011-01', freq='M'))) + assert notnull(pd.Period('2011-01', freq='M')) + + idx = pd.period_range('1/1/1990', periods=20) + assert(notnull(idx).all()) + + idx = pd.PeriodIndex(['NaT', '2011-01', '2011-02'], freq='M') + mask = isnull(idx) + assert(mask[0]) + assert(not mask[1:].any()) + + mask = isnull(idx.asobject) + assert(mask[0]) + assert(not mask[1:].any()) + + mask = notnull(idx) + assert(not mask[0]) + assert(mask[1:].all()) + + mask = notnull(idx.asobject) + assert(not mask[0]) + assert(mask[1:].all()) + class TestIsNull(tm.TestCase): def test_0d_array(self): diff --git a/vb_suite/panel_methods.py b/vb_suite/panel_methods.py index 5e88671a23707..39d20e5fe9d01 100644 --- a/vb_suite/panel_methods.py +++ b/vb_suite/panel_methods.py @@ -8,8 +8,8 @@ # shift setup = common_setup + """ -index = date_range(start="2000", freq="D", periods=1000) -panel = Panel(np.random.randn(100, len(index), 1000)) +index = date_range(start="2000", freq="D", periods=100) +panel = Panel(np.random.randn(100, len(index), 100)) """ panel_shift = Benchmark('panel.shift(1)', setup,