Backport PR #31529: BUG: Series multiplication with timedelta scalar … · pandas-dev/pandas@a8aff6c (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@ Timezones
44 44 Numeric
45 45 ^^^^^^^
46 46 - Bug in dtypes being lost in ``DataFrame.__invert__`` (``~`` operator) with mixed dtypes (:issue:`31183`)
47 +- Bug in :class:`Series` multiplication when multiplying a numeric :class:`Series` with >10000 elements with a timedelta-like scalar (:issue:`31467`)
47 48 -
48 49
49 50 Conversion
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
8 8
9 9 import numpy as np
10 10
11 -from pandas._libs import Timestamp, lib, ops as libops
11 +from pandas._libs import Timedelta, Timestamp, lib, ops as libops
12 12
13 13 from pandas.core.dtypes.cast import (
14 14 construct_1d_object_array_from_listlike,
@@ -184,11 +184,12 @@ def arithmetic_op(
184 184 rvalues = maybe_upcast_for_op(rvalues, lvalues.shape)
185 185
186 186 if should_extension_dispatch(left, rvalues) or isinstance(
187 -rvalues, (ABCTimedeltaArray, ABCDatetimeArray, Timestamp)
187 +rvalues, (ABCTimedeltaArray, ABCDatetimeArray, Timestamp, Timedelta)
188 188 ):
189 189 # TimedeltaArray, DatetimeArray, and Timestamp are included here
190 190 # because they have `freq` attribute which is handled correctly
191 191 # by dispatch_to_extension_op.
192 +# Timedelta is included because numexpr will fail on it, see GH#31457
192 193 res_values = dispatch_to_extension_op(op, lvalues, rvalues)
193 194
194 195 else:
Original file line number Diff line number Diff line change
@@ -176,6 +176,28 @@ def test_numeric_arr_mul_tdscalar(self, scalar_td, numeric_idx, box):
176 176 commute = scalar_td * index
177 177 tm.assert_equal(commute, expected)
178 178
179 +@pytest.mark.parametrize(
180 + "scalar_td",
181 + [
182 + Timedelta(days=1),
183 + Timedelta(days=1).to_timedelta64(),
184 + Timedelta(days=1).to_pytimedelta(),
185 + ],
186 + ids=lambda x: type(x).__name__,
187 + )
188 +def test_numeric_arr_mul_tdscalar_numexpr_path(self, scalar_td, box):
189 +arr = np.arange(2 * 10 ** 4).astype(np.int64)
190 +obj = tm.box_expected(arr, box, transpose=False)
191 +
192 +expected = arr.view("timedelta64[D]").astype("timedelta64[ns]")
193 +expected = tm.box_expected(expected, box, transpose=False)
194 +
195 +result = obj * scalar_td
196 +tm.assert_equal(result, expected)
197 +
198 +result = scalar_td * obj
199 +tm.assert_equal(result, expected)
200 +
179 201 def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
180 202 index = numeric_idx[1:3]
181 203