From a01fa791eafe704ea85e2acc956ad9077e8e7542 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 14 Oct 2018 09:48:40 -0700 Subject: [PATCH] BUG: Fix ndarray + DataFrame ops (#23114) --- doc/source/whatsnew/v0.24.0.txt | 2 +- pandas/core/generic.py | 4 ++++ pandas/tests/arithmetic/test_numeric.py | 2 +- pandas/tests/arithmetic/test_object.py | 3 --- pandas/tests/arithmetic/test_timedelta64.py | 11 ++++------- pandas/tests/frame/test_analytics.py | 5 ++++- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index c03588fe69cd42..d2b702061ff1f3 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -845,7 +845,7 @@ Numeric - Bug in :class:`DataFrame` multiplication between boolean dtype and integer returning ``object`` dtype instead of integer dtype (:issue:`22047`, :issue:`22163`) - Bug in :meth:`DataFrame.apply` where, when supplied with a string argument and additional positional or keyword arguments (e.g. ``df.apply('sum', min_count=1)``), a ``TypeError`` was wrongly raised (:issue:`22376`) - Bug in :meth:`DataFrame.astype` to extension dtype may raise ``AttributeError`` (:issue:`22578`) - +- Bug in :class:`DataFrame` with ``timedelta64[ns]`` dtype arithmetic operations with ``ndarray`` with integer dtype incorrectly treating the narray as ``timedelta64[ns]`` dtype (:issue:`23114`) Strings ^^^^^^^ diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1158a025b13198..ba050bfc8db771 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1795,6 +1795,10 @@ def __round__(self, decimals=0): # ---------------------------------------------------------------------- # Array Interface + # This is also set in IndexOpsMixin + # GH#23114 Ensure ndarray.__op__(DataFrame) returns NotImplemented + __array_priority__ = 1000 + def __array__(self, dtype=None): return com.values_from_object(self) diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index 04492127130480..e9316221b125b8 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -156,7 +156,7 @@ def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box): if box is not pd.Index and broken: # np.timedelta64(3, 'D') / 2 == np.timedelta64(1, 'D') raise pytest.xfail("timedelta64 not converted to nanos; " - "Tick division not imlpemented") + "Tick division not implemented") expected = TimedeltaIndex(['3 Days', '36 Hours']) diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index 64d7cbc47fddd4..511d74a2e790c9 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -140,9 +140,6 @@ def test_objarr_radd_str_invalid(self, dtype, data, box): operator.sub, ops.rsub]) def test_objarr_add_invalid(self, op, box): # invalid ops - if box is pd.DataFrame and op is ops.radd: - pytest.xfail(reason="DataFrame op incorrectly casts the np.array" - "case to M8[ns]") obj_ser = tm.makeObjectSeries() obj_ser.name = 'objects' diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index a8e61b3fd9d3af..fa1a2d9df9a581 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -364,13 +364,13 @@ def test_td64arr_add_str_invalid(self, box): operator.sub, ops.rsub], ids=lambda x: x.__name__) def test_td64arr_add_sub_float(self, box, op, other): + if box is pd.DataFrame and isinstance(other, np.ndarray): + pytest.xfail("Tries to broadcast, raising " + "ValueError instead of TypeError") + tdi = TimedeltaIndex(['-1 days', '-1 days']) tdi = tm.box_expected(tdi, box) - if box is pd.DataFrame and op in [operator.add, operator.sub]: - pytest.xfail(reason="Tries to align incorrectly, " - "raises ValueError") - with pytest.raises(TypeError): op(tdi, other) @@ -1126,9 +1126,6 @@ def test_td64arr_floordiv_tdscalar(self, box, scalar_td): def test_td64arr_rfloordiv_tdscalar(self, box, scalar_td): # GH#18831 - if box is pd.DataFrame and isinstance(scalar_td, np.timedelta64): - pytest.xfail(reason="raises TypeError, not sure why") - td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan diff --git a/pandas/tests/frame/test_analytics.py b/pandas/tests/frame/test_analytics.py index 66bbc1f1a649b5..8864e5fffeb123 100644 --- a/pandas/tests/frame/test_analytics.py +++ b/pandas/tests/frame/test_analytics.py @@ -2046,8 +2046,11 @@ def test_matmul(self): # np.array @ DataFrame result = operator.matmul(a.values, b) + assert isinstance(result, DataFrame) + assert result.columns.equals(b.columns) + assert result.index.equals(pd.Index(range(3))) expected = np.dot(a.values, b.values) - tm.assert_almost_equal(result, expected) + tm.assert_almost_equal(result.values, expected) # nested list @ DataFrame (__rmatmul__) result = operator.matmul(a.values.tolist(), b)