Skip to content

Commit f201232

Browse files
jbrockmendelmeeseeksmachine
authored andcommitted
Backport PR pandas-dev#31529: BUG: Series multiplication with timedelta scalar numexpr path
1 parent 34f6c7e commit f201232

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

doc/source/whatsnew/v1.0.1.rst

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Timezones
4444
Numeric
4545
^^^^^^^
4646
- 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`)
4748
-
4849

4950
Conversion

pandas/core/ops/array_ops.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import numpy as np
1010

11-
from pandas._libs import Timestamp, lib, ops as libops
11+
from pandas._libs import Timedelta, Timestamp, lib, ops as libops
1212

1313
from pandas.core.dtypes.cast import (
1414
construct_1d_object_array_from_listlike,
@@ -184,11 +184,12 @@ def arithmetic_op(
184184
rvalues = maybe_upcast_for_op(rvalues, lvalues.shape)
185185

186186
if should_extension_dispatch(left, rvalues) or isinstance(
187-
rvalues, (ABCTimedeltaArray, ABCDatetimeArray, Timestamp)
187+
rvalues, (ABCTimedeltaArray, ABCDatetimeArray, Timestamp, Timedelta)
188188
):
189189
# TimedeltaArray, DatetimeArray, and Timestamp are included here
190190
# because they have `freq` attribute which is handled correctly
191191
# by dispatch_to_extension_op.
192+
# Timedelta is included because numexpr will fail on it, see GH#31457
192193
res_values = dispatch_to_extension_op(op, lvalues, rvalues)
193194

194195
else:

pandas/tests/arithmetic/test_numeric.py

+22
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,28 @@ def test_numeric_arr_mul_tdscalar(self, scalar_td, numeric_idx, box):
176176
commute = scalar_td * index
177177
tm.assert_equal(commute, expected)
178178

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+
179201
def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box):
180202
index = numeric_idx[1:3]
181203

0 commit comments

Comments
 (0)