Skip to content

Commit

Permalink
PERF: Block.apply (#43609)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel committed Sep 17, 2021
1 parent 7d1c36a commit 2d2e5be
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 15 deletions.
23 changes: 10 additions & 13 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,7 @@ def apply(self, func, **kwargs) -> list[Block]:
apply the function to my values; return a block if we are not
one
"""
with np.errstate(all="ignore"):
result = func(self.values, **kwargs)
result = func(self.values, **kwargs)

return self._split_op_result(result)

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

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

if not isinstance(result, Block):
result = maybe_coerce_values(result)
result = self.make_block(result)
nb = self.make_block(result)

return [result]
return [nb]

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

nb = self.make_block(vals, BlockPlacement(ref_loc))
bp = BlockPlacement(ref_loc)
nb = type(self)(vals, placement=bp, ndim=2)
new_blocks.append(nb)
return new_blocks

Expand Down Expand Up @@ -647,7 +645,7 @@ def copy(self, deep: bool = True):
values = self.values
if deep:
values = values.copy()
return self.make_block_same_class(values)
return type(self)(values, placement=self._mgr_locs, ndim=self.ndim)

# ---------------------------------------------------------------------
# Replace
Expand Down Expand Up @@ -1962,16 +1960,15 @@ def get_block_type(dtype: DtypeObj):
return cls


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

if not isinstance(placement, BlockPlacement):
placement = BlockPlacement(placement)

check_ndim(values, placement, ndim)

if klass is None:
klass = get_block_type(values.dtype)
klass = get_block_type(values.dtype)

values = maybe_coerce_values(values)
return klass(values, ndim=ndim, placement=placement)
Expand Down
13 changes: 11 additions & 2 deletions pandas/tests/apply/test_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,17 @@ def test_apply_np_reducer(float_frame, op, how):
@pytest.mark.parametrize("how", ["transform", "apply"])
def test_apply_np_transformer(float_frame, op, how):
# GH 39116
result = getattr(float_frame, how)(op)
expected = getattr(np, op)(float_frame)

# float_frame will _usually_ have negative values, which will
# trigger the warning here, but let's put one in just to be sure
float_frame.iloc[0, 0] = -1.0
warn = None
if op in ["log", "sqrt"]:
warn = RuntimeWarning

with tm.assert_produces_warning(warn):
result = getattr(float_frame, how)(op)
expected = getattr(np, op)(float_frame)
tm.assert_frame_equal(result, expected)


Expand Down

0 comments on commit 2d2e5be

Please sign in to comment.