Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Fix ndarray + DataFrame ops #23114

Merged
merged 10 commits into from
Oct 14, 2018
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.24.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,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
^^^^^^^
Expand Down
4 changes: 4 additions & 0 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/arithmetic/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'])

Expand Down
3 changes: 0 additions & 3 deletions pandas/tests/arithmetic/test_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
11 changes: 4 additions & 7 deletions pandas/tests/arithmetic/test_timedelta64.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion pandas/tests/frame/test_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down