Skip to content

TYP: annotate Block/BlockManager putmask #32769

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 9 commits into from
Mar 22, 2020
7 changes: 1 addition & 6 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8652,12 +8652,7 @@ def _where(

self._check_inplace_setting(other)
new_data = self._data.putmask(
mask=cond,
new=other,
align=align,
inplace=True,
axis=block_axis,
transpose=self._AXIS_REVERSED,
mask=cond, new=other, align=align, axis=block_axis,
)
self._update_inplace(new_data)

Expand Down
34 changes: 11 additions & 23 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -910,25 +910,26 @@ def setitem(self, indexer, value):

def putmask(
self, mask, new, inplace: bool = False, axis: int = 0, transpose: bool = False,
):
) -> List["Block"]:
"""
putmask the data to the block; it is possible that we may create a
new dtype of block

return the resulting block(s)
Return the resulting block(s).

Parameters
----------
mask : the condition to respect
mask : the condition to respect
new : a ndarray/object
inplace : perform inplace modification, default is False
inplace : bool, default False
Perform inplace modification.
axis : int
transpose : boolean
Set to True if self is stored with axes reversed
transpose : bool, default False
Set to True if self is stored with axes reversed.

Returns
-------
a list of new blocks, the result of the putmask
List[Block]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from numpdoc for Returns section...

"Explanation of the returned values and their types. Similar to the Parameters section, except the name of each return value is optional. The type of each return value is always required"

the pandas docstring guide appears to say the same.

The guides do NOT say this section is optional.

so to comply something like...

Suggested change
List[Block]
list of Block
A list of new blocks, the result of the putmask.

personally, i'd be happy following the google style here.

"Describe the type and semantics of the return value. If the function only returns None, this section is not required. It may also be omitted if the docstring starts with Returns or Yields (e.g. """Returns row from Bigtable as a tuple of strings.""") and the opening sentence is sufficient to describe return value."

and make the returns section optional for internal docstings in the validation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't use google style anywhere, this is quite descriptive.

"""
new_values = self.values if inplace else self.values.copy()

Expand Down Expand Up @@ -1626,23 +1627,10 @@ def set(self, locs, values):
self.values[:] = values

def putmask(
self, mask, new, inplace=False, axis=0, transpose=False,
):
self, mask, new, inplace: bool = False, axis: int = 0, transpose: bool = False,
) -> List["Block"]:
"""
putmask the data to the block; we must be a single block and not
generate other blocks

return the resulting block

Parameters
----------
mask : the condition to respect
new : a ndarray/object
inplace : perform inplace modification, default is False

Returns
-------
a new block, the result of the putmask
See Block.putmask.__doc__
"""
inplace = validate_bool_kwarg(inplace, "inplace")

Expand Down
17 changes: 14 additions & 3 deletions pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,14 +558,25 @@ def where(self, **kwargs) -> "BlockManager":
def setitem(self, indexer, value) -> "BlockManager":
return self.apply("setitem", indexer=indexer, value=value)

def putmask(self, **kwargs):
def putmask(
self, mask, new, align: bool = True, axis: int = 0,
):
transpose = self.ndim == 2

if kwargs.pop("align", True):
if align:
align_keys = ["new", "mask"]
else:
align_keys = ["mask"]

return self.apply("putmask", align_keys=align_keys, **kwargs)
return self.apply(
"putmask",
align_keys=align_keys,
mask=mask,
new=new,
inplace=True,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How feasible is it to align the inplace arg with blocks?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Block.putmask is called from other Block methods with inplace=False, so non-trivial

axis=axis,
transpose=transpose,
)

def diff(self, n: int, axis: int) -> "BlockManager":
return self.apply("diff", n=n, axis=axis)
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,7 @@ def update(self, other) -> None:
other = other.reindex_like(self)
mask = notna(other)

self._data = self._data.putmask(mask=mask, new=other, inplace=True)
self._data = self._data.putmask(mask=mask, new=other)
self._maybe_update_cacher()

# ----------------------------------------------------------------------
Expand Down