Skip to content

Commit bd50388

Browse files
REF: call ensure_wrapped_if_datetimelike before the array arithmetic_op
1 parent 1f8622e commit bd50388

File tree

6 files changed

+33
-10
lines changed

6 files changed

+33
-10
lines changed

pandas/core/arrays/numpy_.py

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from pandas.core import nanops, ops
1717
from pandas.core.arraylike import OpsMixin
1818
from pandas.core.arrays._mixins import NDArrayBackedExtensionArray
19+
from pandas.core.construction import ensure_wrapped_if_datetimelike
1920
from pandas.core.strings.object_array import ObjectStringArrayMixin
2021

2122

@@ -348,6 +349,7 @@ def _cmp_method(self, other, op):
348349
other = other._ndarray
349350

350351
pd_op = ops.get_array_op(op)
352+
other = ensure_wrapped_if_datetimelike(other)
351353
result = pd_op(self._ndarray, other)
352354

353355
if op is divmod or op is ops.rdivmod:

pandas/core/internals/managers.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from pandas.core import ops
3939
import pandas.core.algorithms as algos
4040
from pandas.core.arrays.sparse import SparseDtype
41-
from pandas.core.construction import extract_array
41+
from pandas.core.construction import ensure_wrapped_if_datetimelike, extract_array
4242
from pandas.core.indexers import maybe_convert_indices
4343
from pandas.core.indexes.api import Float64Index, Index, ensure_index
4444
from pandas.core.internals.base import DataManager
@@ -382,7 +382,20 @@ def operate_scalar(self, other: Scalar, op) -> BlockManager:
382382
"""
383383
# Get the appropriate array-op to apply to each column/block's values.
384384
array_op = ops.get_array_op(op)
385-
return self.apply(array_op, right=other)
385+
result_blocks: List[Block] = []
386+
387+
for b in self.blocks:
388+
left = ensure_wrapped_if_datetimelike(b.values)
389+
with np.errstate(all="ignore"):
390+
result = array_op(left, right=other)
391+
392+
applied = b._split_op_result(result)
393+
result_blocks = extend_blocks(applied, result_blocks)
394+
395+
if len(result_blocks) == 0:
396+
return self.make_empty(self.axes)
397+
398+
return type(self).from_blocks(result_blocks, self.axes)
386399

387400
def operate_array(self, other: ArrayLike, op, axis: int) -> BlockManager:
388401
"""

pandas/core/internals/ops.py

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
from pandas._typing import ArrayLike
99

10+
from pandas.core.construction import ensure_wrapped_if_datetimelike
11+
1012
if TYPE_CHECKING:
1113
from pandas.core.internals.blocks import Block
1214
from pandas.core.internals.managers import BlockManager
@@ -53,6 +55,8 @@ def operate_blockwise(
5355

5456
res_blks: List[Block] = []
5557
for lvals, rvals, locs, left_ea, right_ea, rblk in _iter_block_pairs(left, right):
58+
lvals = ensure_wrapped_if_datetimelike(lvals)
59+
rvals = ensure_wrapped_if_datetimelike(rvals)
5660
res_values = array_op(lvals, rvals)
5761
if left_ea and not right_ea and hasattr(res_values, "reshape"):
5862
res_values = res_values.reshape(1, -1)

pandas/core/ops/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from pandas.core.dtypes.missing import isna
2121

2222
from pandas.core import algorithms
23+
from pandas.core.construction import ensure_wrapped_if_datetimelike
2324
from pandas.core.ops.array_ops import ( # noqa:F401
2425
arithmetic_op,
2526
comp_method_OBJECT_ARRAY,
@@ -124,6 +125,8 @@ def fill_binop(left, right, fill_value):
124125
right = right.copy()
125126
right[right_mask & mask] = fill_value
126127

128+
left = ensure_wrapped_if_datetimelike(left)
129+
right = ensure_wrapped_if_datetimelike(right)
127130
return left, right
128131

129132

pandas/core/ops/array_ops.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -174,19 +174,17 @@ def arithmetic_op(left: ArrayLike, right: Any, op):
174174
Or a 2-tuple of these in the case of divmod or rdivmod.
175175
"""
176176

177-
# NB: We assume that extract_array has already been called
178-
# on `left` and `right`.
179-
lvalues = ensure_wrapped_if_datetimelike(left)
180-
rvalues = ensure_wrapped_if_datetimelike(right)
181-
rvalues = _maybe_upcast_for_op(rvalues, lvalues.shape)
177+
# NB: We assume that extract_array and ensure_wrapped_if_datetimelike
178+
# has already been called on `left` and `right`.
179+
right = _maybe_upcast_for_op(right, left.shape)
182180

183-
if should_extension_dispatch(lvalues, rvalues) or isinstance(rvalues, Timedelta):
181+
if should_extension_dispatch(left, right) or isinstance(right, Timedelta):
184182
# Timedelta is included because numexpr will fail on it, see GH#31457
185-
res_values = op(lvalues, rvalues)
183+
res_values = op(left, right)
186184

187185
else:
188186
with np.errstate(all="ignore"):
189-
res_values = _na_arithmetic_op(lvalues, rvalues, op)
187+
res_values = _na_arithmetic_op(left, right, op)
190188

191189
return res_values
192190

pandas/core/series.py

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import pandas.core.common as com
8383
from pandas.core.construction import (
8484
create_series_with_explicit_dtype,
85+
ensure_wrapped_if_datetimelike,
8586
extract_array,
8687
is_empty_data,
8788
sanitize_array,
@@ -5016,6 +5017,8 @@ def _arith_method(self, other, op):
50165017

50175018
lvalues = extract_array(self, extract_numpy=True)
50185019
rvalues = extract_array(other, extract_numpy=True)
5020+
lvalues = ensure_wrapped_if_datetimelike(lvalues)
5021+
rvalues = ensure_wrapped_if_datetimelike(rvalues)
50195022
result = ops.arithmetic_op(lvalues, rvalues, op)
50205023

50215024
return self._construct_result(result, name=res_name)

0 commit comments

Comments
 (0)