Skip to content

Commit 6a6bb40

Browse files
jbrockmendeljreback
authored andcommitted
Fix Index mul/div ops with Series, closes #19080, #19042 (#19253)
1 parent 4ebdc50 commit 6a6bb40

File tree

5 files changed

+32
-20
lines changed

5 files changed

+32
-20
lines changed

doc/source/whatsnew/v0.23.0.txt

+3
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ Conversion
423423
- Bug in :class:`WeekOfMonth` and :class:`LastWeekOfMonth` where default keyword arguments for constructor raised ``ValueError`` (:issue:`19142`)
424424
- Bug in localization of a naive, datetime string in a ``Series`` constructor with a ``datetime64[ns, tz]`` dtype (:issue:`174151`)
425425
- :func:`Timestamp.replace` will now handle Daylight Savings transitions gracefully (:issue:`18319`)
426+
- 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`)
427+
428+
426429
-
427430
-
428431
- Bug in ``.astype()`` to non-ns timedelta units would hold the incorrect dtype (:issue:`19176`, :issue:`19223`, :issue:`12425`)

pandas/core/indexes/base.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from pandas.core.accessor import CachedAccessor
1616
from pandas.core.dtypes.generic import (
17-
ABCSeries,
17+
ABCSeries, ABCDataFrame,
1818
ABCMultiIndex,
1919
ABCPeriodIndex,
2020
ABCDateOffset)
@@ -4019,6 +4019,9 @@ def _add_numeric_methods_binary(cls):
40194019

40204020
def _make_evaluate_binop(op, opstr, reversed=False, constructor=Index):
40214021
def _evaluate_numeric_binop(self, other):
4022+
if isinstance(other, (ABCSeries, ABCDataFrame)):
4023+
return NotImplemented
4024+
40224025
other = self._validate_for_numeric_binop(other, op, opstr)
40234026

40244027
# handle time-based others

pandas/core/indexes/range.py

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
is_integer,
99
is_scalar,
1010
is_int64_dtype)
11+
from pandas.core.dtypes.generic import ABCSeries
1112

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

585586
def _evaluate_numeric_binop(self, other):
587+
if isinstance(other, ABCSeries):
588+
return NotImplemented
586589

587590
other = self._validate_for_numeric_binop(other, op, opstr)
588591
attrs = self._get_attributes_dict()

pandas/tests/indexes/test_numeric.py

+17-15
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ def test_numeric_compat(self):
6868
tm.assert_index_equal(result, didx)
6969

7070
result = idx * Series(np.arange(5, dtype=arr_dtype))
71-
tm.assert_index_equal(result, didx)
71+
tm.assert_series_equal(result, Series(didx))
7272

73-
result = idx * Series(np.arange(5, dtype='float64') + 0.1)
74-
expected = Float64Index(np.arange(5, dtype='float64') *
75-
(np.arange(5, dtype='float64') + 0.1))
76-
tm.assert_index_equal(result, expected)
73+
rng5 = np.arange(5, dtype='float64')
74+
result = idx * Series(rng5 + 0.1)
75+
expected = Series(rng5 * (rng5 + 0.1))
76+
tm.assert_series_equal(result, expected)
7777

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

98-
result = divmod(idx, Series(full_like(idx.values, 2)))
99-
with np.errstate(all='ignore'):
100-
div, mod = divmod(
101-
idx.values,
102-
full_like(idx.values, 2),
103-
)
104-
expected = Index(div), Index(mod)
105-
for r, e in zip(result, expected):
106-
tm.assert_index_equal(r, e)
107-
10898
# test power calculations both ways, GH 14973
10999
expected = pd.Float64Index(2.0**idx.values)
110100
result = 2.0**idx
@@ -114,6 +104,18 @@ def test_numeric_compat(self):
114104
result = idx**2.0
115105
tm.assert_index_equal(result, expected)
116106

107+
@pytest.mark.xfail(reason='GH#19252 Series has no __rdivmod__')
108+
def test_divmod_series(self):
109+
idx = self.create_index()
110+
111+
result = divmod(idx, Series(full_like(idx.values, 2)))
112+
with np.errstate(all='ignore'):
113+
div, mod = divmod(idx.values, full_like(idx.values, 2))
114+
expected = Series(div), Series(mod)
115+
116+
for r, e in zip(result, expected):
117+
tm.assert_series_equal(r, e)
118+
117119
def test_explicit_conversions(self):
118120

119121
# GH 8608

pandas/tests/indexes/timedeltas/test_arithmetic.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,12 @@ def test_numeric_compat(self):
152152
tm.assert_index_equal(result, didx)
153153

154154
result = idx * Series(np.arange(5, dtype='int64'))
155-
tm.assert_index_equal(result, didx)
155+
tm.assert_series_equal(result, Series(didx))
156156

157-
result = idx * Series(np.arange(5, dtype='float64') + 0.1)
158-
tm.assert_index_equal(result, self._holder(np.arange(
159-
5, dtype='float64') * (np.arange(5, dtype='float64') + 0.1)))
157+
rng5 = np.arange(5, dtype='float64')
158+
result = idx * Series(rng5 + 0.1)
159+
tm.assert_series_equal(result,
160+
Series(self._holder(rng5 * (rng5 + 0.1))))
160161

161162
# invalid
162163
pytest.raises(TypeError, lambda: idx * idx)

0 commit comments

Comments
 (0)