diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 2ff195fa8e5d2..0dda83f4e9c3f 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -555,6 +555,8 @@ def replace( to_replace, value, inplace: bool = False, + # conversion is done at the end if we're called from replace_list + convert: bool = True, # mask may be pre-computed if we're called from replace_list mask: npt.NDArray[np.bool_] | None = None, ) -> list[Block]: @@ -572,6 +574,7 @@ def replace( if isinstance(values, Categorical): # TODO: avoid special-casing blk = self if inplace else self.copy() + # TODO: should we pass convert here? moot point if special casing avoided. blk.values._replace(to_replace=to_replace, value=value, inplace=True) return [blk] @@ -592,7 +595,7 @@ def replace( elif self._can_hold_element(value): blk = self if inplace else self.copy() putmask_inplace(blk.values, mask, value) - if not (self.is_object and value is None): + if convert and not (self.is_object and value is None): # if the user *explicitly* gave None, we keep None, otherwise # may downcast to NaN blocks = blk.convert(numeric=False, copy=False) @@ -606,6 +609,7 @@ def replace( to_replace=to_replace, value=value, inplace=True, + convert=convert, mask=mask, ) @@ -619,6 +623,7 @@ def replace( to_replace=to_replace, value=value, inplace=True, + convert=convert, mask=mask[i : i + 1], ) ) @@ -630,8 +635,10 @@ def _replace_regex( to_replace, value, inplace: bool = False, + # conversion is done at the end if we're called from replace_list convert: bool = True, - mask=None, + # mask may be pre-computed if we're called from replace_list + mask: npt.NDArray[np.bool_] | None = None, ) -> list[Block]: """ Replace elements by the given value. @@ -664,7 +671,10 @@ def _replace_regex( replace_regex(new_values, rx, value, mask) block = self.make_block(new_values) - return block.convert(numeric=False, copy=False) + if convert: + return block.convert(numeric=False, copy=False) + else: + return [block] @final def replace_list( @@ -707,7 +717,7 @@ def replace_list( masks = [extract_bool_array(x) for x in masks] # type: ignore[arg-type] rb = [self if inplace else self.copy()] - for i, (src, dest) in enumerate(pairs): + for i, (to_replace, value) in enumerate(pairs): convert = i == src_len # only convert once at the end new_rb: list[Block] = [] @@ -723,8 +733,8 @@ def replace_list( m = mib[blk_num : blk_num + 1] result = blk._replace_coerce( - to_replace=src, - value=dest, + to_replace=to_replace, + value=value, mask=m, inplace=inplace, regex=regex, @@ -785,7 +795,11 @@ def _replace_coerce( putmask_inplace(nb.values, mask, value) return [nb] return self.replace( - to_replace=to_replace, value=value, inplace=inplace, mask=mask + to_replace=to_replace, + value=value, + inplace=inplace, + convert=False, + mask=mask, ) # ---------------------------------------------------------------------