Skip to content

Commit 2d2e5be

Browse files
authored
PERF: Block.apply (pandas-dev#43609)
1 parent 7d1c36a commit 2d2e5be

File tree

2 files changed

+21
-15
lines changed

2 files changed

+21
-15
lines changed

pandas/core/internals/blocks.py

+10-13
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,7 @@ def apply(self, func, **kwargs) -> list[Block]:
372372
apply the function to my values; return a block if we are not
373373
one
374374
"""
375-
with np.errstate(all="ignore"):
376-
result = func(self.values, **kwargs)
375+
result = func(self.values, **kwargs)
377376

378377
return self._split_op_result(result)
379378

@@ -399,9 +398,9 @@ def reduce(self, func, ignore_failures: bool = False) -> list[Block]:
399398
return [nb]
400399

401400
@final
402-
def _split_op_result(self, result) -> list[Block]:
401+
def _split_op_result(self, result: ArrayLike) -> list[Block]:
403402
# See also: split_and_operate
404-
if is_extension_array_dtype(result) and result.ndim > 1:
403+
if result.ndim > 1 and isinstance(result.dtype, ExtensionDtype):
405404
# TODO(EA2D): unnecessary with 2D EAs
406405
# if we get a 2D ExtensionArray, we need to split it into 1D pieces
407406
nbs = []
@@ -415,11 +414,9 @@ def _split_op_result(self, result) -> list[Block]:
415414
nbs.append(block)
416415
return nbs
417416

418-
if not isinstance(result, Block):
419-
result = maybe_coerce_values(result)
420-
result = self.make_block(result)
417+
nb = self.make_block(result)
421418

422-
return [result]
419+
return [nb]
423420

424421
def fillna(
425422
self, value, limit=None, inplace: bool = False, downcast=None
@@ -474,7 +471,8 @@ def _split(self) -> list[Block]:
474471
for i, ref_loc in enumerate(self._mgr_locs):
475472
vals = self.values[slice(i, i + 1)]
476473

477-
nb = self.make_block(vals, BlockPlacement(ref_loc))
474+
bp = BlockPlacement(ref_loc)
475+
nb = type(self)(vals, placement=bp, ndim=2)
478476
new_blocks.append(nb)
479477
return new_blocks
480478

@@ -647,7 +645,7 @@ def copy(self, deep: bool = True):
647645
values = self.values
648646
if deep:
649647
values = values.copy()
650-
return self.make_block_same_class(values)
648+
return type(self)(values, placement=self._mgr_locs, ndim=self.ndim)
651649

652650
# ---------------------------------------------------------------------
653651
# Replace
@@ -1962,16 +1960,15 @@ def get_block_type(dtype: DtypeObj):
19621960
return cls
19631961

19641962

1965-
def new_block(values, placement, *, ndim: int, klass=None) -> Block:
1963+
def new_block(values, placement, *, ndim: int) -> Block:
19661964
# caller is responsible for ensuring values is NOT a PandasArray
19671965

19681966
if not isinstance(placement, BlockPlacement):
19691967
placement = BlockPlacement(placement)
19701968

19711969
check_ndim(values, placement, ndim)
19721970

1973-
if klass is None:
1974-
klass = get_block_type(values.dtype)
1971+
klass = get_block_type(values.dtype)
19751972

19761973
values = maybe_coerce_values(values)
19771974
return klass(values, ndim=ndim, placement=placement)

pandas/tests/apply/test_str.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,17 @@ def test_apply_np_reducer(float_frame, op, how):
7272
@pytest.mark.parametrize("how", ["transform", "apply"])
7373
def test_apply_np_transformer(float_frame, op, how):
7474
# GH 39116
75-
result = getattr(float_frame, how)(op)
76-
expected = getattr(np, op)(float_frame)
75+
76+
# float_frame will _usually_ have negative values, which will
77+
# trigger the warning here, but let's put one in just to be sure
78+
float_frame.iloc[0, 0] = -1.0
79+
warn = None
80+
if op in ["log", "sqrt"]:
81+
warn = RuntimeWarning
82+
83+
with tm.assert_produces_warning(warn):
84+
result = getattr(float_frame, how)(op)
85+
expected = getattr(np, op)(float_frame)
7786
tm.assert_frame_equal(result, expected)
7887

7988

0 commit comments

Comments
 (0)