diff --git a/doc/source/whatsnew/v0.18.0.txt b/doc/source/whatsnew/v0.18.0.txt index c1f14ce6703a0..ce324e8a2dab1 100644 --- a/doc/source/whatsnew/v0.18.0.txt +++ b/doc/source/whatsnew/v0.18.0.txt @@ -445,7 +445,7 @@ Bug Fixes - Accept unicode in ``Timedelta`` constructor (:issue:`11995`) - Bug in value label reading for ``StataReader`` when reading incrementally (:issue:`12014`) - Bug in vectorized ``DateOffset`` when ``n`` parameter is ``0`` (:issue:`11370`) - +- Compat for numpy 1.11 w.r.t. ``NaT`` comparison changes (:issue:`12049`) diff --git a/pandas/core/common.py b/pandas/core/common.py index b80b7eecaeb11..0326352ef3444 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -379,12 +379,13 @@ def array_equivalent(left, right, strict_nan=False): """ left, right = np.asarray(left), np.asarray(right) + + # shape compat if left.shape != right.shape: return False # Object arrays can contain None, NaN and NaT. - if (issubclass(left.dtype.type, np.object_) or - issubclass(right.dtype.type, np.object_)): + if is_object_dtype(left) or is_object_dtype(right): if not strict_nan: # pd.isnull considers NaN and None to be equivalent. @@ -405,13 +406,21 @@ def array_equivalent(left, right, strict_nan=False): return True # NaNs can occur in float and complex arrays. - if issubclass(left.dtype.type, (np.floating, np.complexfloating)): + if is_float_dtype(left) or is_complex_dtype(left): return ((left == right) | (np.isnan(left) & np.isnan(right))).all() # numpy will will not allow this type of datetimelike vs integer comparison elif is_datetimelike_v_numeric(left, right): return False + # M8/m8 + elif needs_i8_conversion(left) and needs_i8_conversion(right): + if not is_dtype_equal(left.dtype, right.dtype): + return False + + left = left.view('i8') + right = right.view('i8') + # NaNs cannot occur otherwise. return np.array_equal(left, right) diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index bc204740567de..a22d8f11c9a75 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -8,7 +8,9 @@ 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 (Series, DataFrame, date_range, + DatetimeIndex, TimedeltaIndex, + Timestamp, Float64Index) from pandas import compat from pandas.compat import range, long, lrange, lmap, u from pandas.core.common import notnull, isnull, array_equivalent @@ -322,20 +324,40 @@ def test_array_equivalent(): np.array([np.nan, 1, np.nan])) assert array_equivalent(np.array([np.nan, None], dtype='object'), np.array([np.nan, None], dtype='object')) - assert array_equivalent(np.array([np.nan, 1+1j], dtype='complex'), - np.array([np.nan, 1+1j], dtype='complex')) - assert not array_equivalent(np.array([np.nan, 1+1j], dtype='complex'), - np.array([np.nan, 1+2j], dtype='complex')) + assert array_equivalent(np.array([np.nan, 1 + 1j], dtype='complex'), + np.array([np.nan, 1 + 1j], dtype='complex')) + assert not array_equivalent(np.array([np.nan, 1 + 1j], dtype='complex'), + np.array([np.nan, 1 + 2j], dtype='complex')) assert not array_equivalent(np.array([np.nan, 1, np.nan]), np.array([np.nan, 2, np.nan])) - assert not array_equivalent(np.array(['a', 'b', 'c', 'd']), np.array(['e', 'e'])) - assert array_equivalent(Float64Index([0, np.nan]), Float64Index([0, np.nan])) - assert not array_equivalent(Float64Index([0, np.nan]), Float64Index([1, np.nan])) - assert array_equivalent(DatetimeIndex([0, np.nan]), DatetimeIndex([0, np.nan])) - assert not array_equivalent(DatetimeIndex([0, np.nan]), DatetimeIndex([1, np.nan])) + assert not array_equivalent(np.array(['a', 'b', 'c', 'd']), + np.array(['e', 'e'])) + assert array_equivalent(Float64Index([0, np.nan]), + Float64Index([0, np.nan])) + assert not array_equivalent(Float64Index([0, np.nan]), + Float64Index([1, np.nan])) + assert array_equivalent(DatetimeIndex([0, np.nan]), + DatetimeIndex([0, np.nan])) + assert not array_equivalent(DatetimeIndex([0, np.nan]), + DatetimeIndex([1, np.nan])) + assert array_equivalent(TimedeltaIndex([0, np.nan]), + TimedeltaIndex([0, np.nan])) + assert not array_equivalent(TimedeltaIndex([0, np.nan]), + TimedeltaIndex([1, np.nan])) + assert array_equivalent(DatetimeIndex([0, np.nan], tz='US/Eastern'), + DatetimeIndex([0, np.nan], tz='US/Eastern')) + assert not array_equivalent(DatetimeIndex([0, np.nan], tz='US/Eastern'), + DatetimeIndex([1, np.nan], tz='US/Eastern')) + assert not array_equivalent(DatetimeIndex([0, np.nan]), + DatetimeIndex([0, np.nan], tz='US/Eastern')) + assert not array_equivalent(DatetimeIndex([0, np.nan], tz='CET'), + DatetimeIndex([0, np.nan], tz='US/Eastern')) + assert not array_equivalent(DatetimeIndex([0, np.nan]), + TimedeltaIndex([0, np.nan])) + def test_datetimeindex_from_empty_datetime64_array(): - for unit in [ 'ms', 'us', 'ns' ]: + for unit in ['ms', 'us', 'ns']: idx = DatetimeIndex(np.array([], dtype='datetime64[%s]' % unit)) assert(len(idx) == 0) diff --git a/pandas/tseries/tests/test_tslib.py b/pandas/tseries/tests/test_tslib.py index ba43537ee609b..55a6bf6f13b63 100644 --- a/pandas/tseries/tests/test_tslib.py +++ b/pandas/tseries/tests/test_tslib.py @@ -399,8 +399,10 @@ def test_asm8(self): 1000, ] for n in ns: - self.assertEqual(Timestamp(n).asm8, np.datetime64(n, 'ns'), n) - self.assertEqual(Timestamp('nat').asm8, np.datetime64('nat', 'ns')) + self.assertEqual(Timestamp(n).asm8.view('i8'), + np.datetime64(n, 'ns').view('i8'), n) + self.assertEqual(Timestamp('nat').asm8.view('i8'), + np.datetime64('nat', 'ns').view('i8')) def test_fields(self): @@ -752,13 +754,11 @@ def test_coercing_dates_outside_of_datetime64_ns_bounds(self): np.array([invalid_date], dtype='object'), errors='raise', ) - self.assertTrue( - np.array_equal( - tslib.array_to_datetime( - np.array([invalid_date], dtype='object'), errors='coerce', - ), - np.array([tslib.iNaT], dtype='M8[ns]') - ) + self.assert_numpy_array_equal( + tslib.array_to_datetime( + np.array([invalid_date], dtype='object'), + errors='coerce'), + np.array([tslib.iNaT], dtype='M8[ns]') ) arr = np.array(['1/1/1000', '1/1/2000'], dtype=object)