Skip to content

CLN: _replace_single #37683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 34 additions & 48 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,6 @@ def replace(
value,
inplace: bool = False,
regex: bool = False,
convert: bool = True,
) -> List["Block"]:
"""
replace the to_replace value with value, possible to create new
Expand Down Expand Up @@ -755,9 +754,7 @@ def replace(
if len(to_replace) == 1:
# _can_hold_element checks have reduced this back to the
# scalar case and we can avoid a costly object cast
return self.replace(
to_replace[0], value, inplace=inplace, regex=regex, convert=convert
)
return self.replace(to_replace[0], value, inplace=inplace, regex=regex)

# GH 22083, TypeError or ValueError occurred within error handling
# causes infinite loop. Cast and retry only if not objectblock.
Expand All @@ -771,7 +768,6 @@ def replace(
value=value,
inplace=inplace,
regex=regex,
convert=convert,
)

values = self.values
Expand Down Expand Up @@ -810,16 +806,21 @@ def replace(
value=value,
inplace=inplace,
regex=regex,
convert=convert,
)
if convert:
blocks = extend_blocks(
[b.convert(numeric=False, copy=not inplace) for b in blocks]
)

blocks = extend_blocks(
[b.convert(numeric=False, copy=not inplace) for b in blocks]
)
return blocks

def _replace_single(
self, to_replace, value, inplace=False, regex=False, convert=True, mask=None
self,
to_replace,
value,
inplace: bool = False,
regex: bool = False,
convert: bool = True,
mask=None,
) -> List["Block"]:
""" no-op on a non-ObjectBlock """
return [self] if inplace else [self.copy()]
Expand Down Expand Up @@ -860,9 +861,9 @@ def comp(s: Scalar, mask: np.ndarray, regex: bool = False) -> np.ndarray:
m = masks[i]
convert = i == src_len # only convert once at the end
result = blk._replace_coerce(
mask=m,
to_replace=src,
value=dest,
mask=m,
inplace=inplace,
regex=regex,
)
Expand Down Expand Up @@ -1567,9 +1568,9 @@ def _replace_coerce(
self,
to_replace,
value,
mask: np.ndarray,
inplace: bool = True,
regex: bool = False,
mask=None,
) -> List["Block"]:
"""
Replace value corresponding to the given boolean array with another
Expand All @@ -1581,12 +1582,12 @@ def _replace_coerce(
Scalar to replace or regular expression to match.
value : object
Replacement object.
mask : np.ndarray[bool]
True indicate corresponding element is ignored.
inplace : bool, default True
Perform inplace modification.
regex : bool, default False
If true, perform regular expression substitution.
mask : array-like of bool, optional
True indicate corresponding element is ignored.

Returns
-------
Expand Down Expand Up @@ -2495,7 +2496,11 @@ def _can_hold_element(self, element: Any) -> bool:
return True

def replace(
self, to_replace, value, inplace=False, regex=False, convert=True
self,
to_replace,
value,
inplace: bool = False,
regex: bool = False,
) -> List["Block"]:
to_rep_is_list = is_list_like(to_replace)
value_is_list = is_list_like(value)
Expand All @@ -2506,20 +2511,14 @@ def replace(
blocks: List["Block"] = [self]

if not either_list and is_re(to_replace):
return self._replace_single(
to_replace, value, inplace=inplace, regex=True, convert=convert
)
return self._replace_single(to_replace, value, inplace=inplace, regex=True)
elif not (either_list or regex):
return super().replace(
to_replace, value, inplace=inplace, regex=regex, convert=convert
)
return super().replace(to_replace, value, inplace=inplace, regex=regex)
elif both_lists:
for to_rep, v in zip(to_replace, value):
result_blocks = []
for b in blocks:
result = b._replace_single(
to_rep, v, inplace=inplace, regex=regex, convert=convert
)
result = b._replace_single(to_rep, v, inplace=inplace, regex=regex)
result_blocks.extend(result)
blocks = result_blocks
return result_blocks
Expand All @@ -2529,18 +2528,22 @@ def replace(
result_blocks = []
for b in blocks:
result = b._replace_single(
to_rep, value, inplace=inplace, regex=regex, convert=convert
to_rep, value, inplace=inplace, regex=regex
)
result_blocks.extend(result)
blocks = result_blocks
return result_blocks

return self._replace_single(
to_replace, value, inplace=inplace, convert=convert, regex=regex
)
return self._replace_single(to_replace, value, inplace=inplace, regex=regex)

def _replace_single(
self, to_replace, value, inplace=False, regex=False, convert=True, mask=None
self,
to_replace,
value,
inplace: bool = False,
regex: bool = False,
convert: bool = True,
mask=None,
) -> List["Block"]:
"""
Replace elements by the given value.
Expand All @@ -2567,23 +2570,7 @@ def _replace_single(
inplace = validate_bool_kwarg(inplace, "inplace")

# to_replace is regex compilable
to_rep_re = regex and is_re_compilable(to_replace)

# regex is regex compilable
regex_re = is_re_compilable(regex)

# only one will survive
if to_rep_re and regex_re:
raise AssertionError(
"only one of to_replace and regex can be regex compilable"
)

# if regex was passed as something that can be a regex (rather than a
# boolean)
if regex_re:
to_replace = regex

regex = regex_re or to_rep_re
regex = regex and is_re_compilable(to_replace)

# try to get the pattern attribute (compiled re) or it's a string
if is_re(to_replace):
Expand Down Expand Up @@ -2646,7 +2633,6 @@ def replace(
value,
inplace: bool = False,
regex: bool = False,
convert: bool = True,
) -> List["Block"]:
inplace = validate_bool_kwarg(inplace, "inplace")
result = self if inplace else self.copy()
Expand Down
6 changes: 4 additions & 2 deletions pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,9 +638,11 @@ def convert(
coerce=coerce,
)

def replace(self, value, **kwargs) -> "BlockManager":
def replace(self, to_replace, value, inplace: bool, regex: bool) -> "BlockManager":
assert np.ndim(value) == 0, value
return self.apply("replace", value=value, **kwargs)
return self.apply(
"replace", to_replace=to_replace, value=value, inplace=inplace, regex=regex
)

def replace_list(
self: T,
Expand Down