Skip to content

Commit

Permalink
Fix Index mul/div ops with Series, closes #19080, #19042 (#19253)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and jreback committed Jan 16, 2018
1 parent 4ebdc50 commit 6a6bb40
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 20 deletions.
3 changes: 3 additions & 0 deletions doc/source/whatsnew/v0.23.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,9 @@ Conversion
- Bug in :class:`WeekOfMonth` and :class:`LastWeekOfMonth` where default keyword arguments for constructor raised ``ValueError`` (:issue:`19142`)
- Bug in localization of a naive, datetime string in a ``Series`` constructor with a ``datetime64[ns, tz]`` dtype (:issue:`174151`)
- :func:`Timestamp.replace` will now handle Daylight Savings transitions gracefully (:issue:`18319`)
- Bug in :class:`Index` multiplication and division methods where operating with a ``Series`` would return an ``Index`` object instead of a ``Series`` object (:issue:`19042`)


-
-
- Bug in ``.astype()`` to non-ns timedelta units would hold the incorrect dtype (:issue:`19176`, :issue:`19223`, :issue:`12425`)
Expand Down
5 changes: 4 additions & 1 deletion pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from pandas.core.accessor import CachedAccessor
from pandas.core.dtypes.generic import (
ABCSeries,
ABCSeries, ABCDataFrame,
ABCMultiIndex,
ABCPeriodIndex,
ABCDateOffset)
Expand Down Expand Up @@ -4019,6 +4019,9 @@ def _add_numeric_methods_binary(cls):

def _make_evaluate_binop(op, opstr, reversed=False, constructor=Index):
def _evaluate_numeric_binop(self, other):
if isinstance(other, (ABCSeries, ABCDataFrame)):
return NotImplemented

other = self._validate_for_numeric_binop(other, op, opstr)

# handle time-based others
Expand Down
3 changes: 3 additions & 0 deletions pandas/core/indexes/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
is_integer,
is_scalar,
is_int64_dtype)
from pandas.core.dtypes.generic import ABCSeries

from pandas import compat
from pandas.compat import lrange, range, get_range_parameters
Expand Down Expand Up @@ -583,6 +584,8 @@ def _make_evaluate_binop(op, opstr, reversed=False, step=False):
"""

def _evaluate_numeric_binop(self, other):
if isinstance(other, ABCSeries):
return NotImplemented

other = self._validate_for_numeric_binop(other, op, opstr)
attrs = self._get_attributes_dict()
Expand Down
32 changes: 17 additions & 15 deletions pandas/tests/indexes/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ def test_numeric_compat(self):
tm.assert_index_equal(result, didx)

result = idx * Series(np.arange(5, dtype=arr_dtype))
tm.assert_index_equal(result, didx)
tm.assert_series_equal(result, Series(didx))

result = idx * Series(np.arange(5, dtype='float64') + 0.1)
expected = Float64Index(np.arange(5, dtype='float64') *
(np.arange(5, dtype='float64') + 0.1))
tm.assert_index_equal(result, expected)
rng5 = np.arange(5, dtype='float64')
result = idx * Series(rng5 + 0.1)
expected = Series(rng5 * (rng5 + 0.1))
tm.assert_series_equal(result, expected)

# invalid
pytest.raises(TypeError,
Expand All @@ -95,16 +95,6 @@ def test_numeric_compat(self):
for r, e in zip(result, expected):
tm.assert_index_equal(r, e)

result = divmod(idx, Series(full_like(idx.values, 2)))
with np.errstate(all='ignore'):
div, mod = divmod(
idx.values,
full_like(idx.values, 2),
)
expected = Index(div), Index(mod)
for r, e in zip(result, expected):
tm.assert_index_equal(r, e)

# test power calculations both ways, GH 14973
expected = pd.Float64Index(2.0**idx.values)
result = 2.0**idx
Expand All @@ -114,6 +104,18 @@ def test_numeric_compat(self):
result = idx**2.0
tm.assert_index_equal(result, expected)

@pytest.mark.xfail(reason='GH#19252 Series has no __rdivmod__')
def test_divmod_series(self):
idx = self.create_index()

result = divmod(idx, Series(full_like(idx.values, 2)))
with np.errstate(all='ignore'):
div, mod = divmod(idx.values, full_like(idx.values, 2))
expected = Series(div), Series(mod)

for r, e in zip(result, expected):
tm.assert_series_equal(r, e)

def test_explicit_conversions(self):

# GH 8608
Expand Down
9 changes: 5 additions & 4 deletions pandas/tests/indexes/timedeltas/test_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,12 @@ def test_numeric_compat(self):
tm.assert_index_equal(result, didx)

result = idx * Series(np.arange(5, dtype='int64'))
tm.assert_index_equal(result, didx)
tm.assert_series_equal(result, Series(didx))

result = idx * Series(np.arange(5, dtype='float64') + 0.1)
tm.assert_index_equal(result, self._holder(np.arange(
5, dtype='float64') * (np.arange(5, dtype='float64') + 0.1)))
rng5 = np.arange(5, dtype='float64')
result = idx * Series(rng5 + 0.1)
tm.assert_series_equal(result,
Series(self._holder(rng5 * (rng5 + 0.1))))

# invalid
pytest.raises(TypeError, lambda: idx * idx)
Expand Down

0 comments on commit 6a6bb40

Please sign in to comment.