Skip to content

DEPR: Grouper.ax, Grouper.obj, Grouper.indexer #51206

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
Feb 9, 2023
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
3 changes: 3 additions & 0 deletions doc/source/whatsnew/v2.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,9 @@ Deprecations
- Deprecated calling ``float`` or ``int`` on a single element :class:`Series` to return a ``float`` or ``int`` respectively. Extract the element before calling ``float`` or ``int`` instead (:issue:`51101`)
- Deprecated :meth:`Grouper.groups`, use :meth:`Groupby.groups` instead (:issue:`51182`)
- Deprecated :meth:`Grouper.grouper`, use :meth:`Groupby.grouper` instead (:issue:`51182`)
- Deprecated :meth:`Grouper.obj`, use :meth:`Groupby.obj` instead (:issue:`51206`)
- Deprecated :meth:`Grouper.indexer`, use :meth:`Resampler.indexer` instead (:issue:`51206`)
- Deprecated :meth:`Grouper.ax`, use :meth:`Resampler.ax` instead (:issue:`51206`)
- Deprecated :meth:`Series.pad` in favor of :meth:`Series.ffill` (:issue:`33396`)
- Deprecated :meth:`Series.backfill` in favor of :meth:`Series.bfill` (:issue:`33396`)
- Deprecated :meth:`DataFrame.pad` in favor of :meth:`DataFrame.ffill` (:issue:`33396`)
Expand Down
61 changes: 46 additions & 15 deletions pandas/core/groupby/grouper.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,21 +270,13 @@ def __init__(
self.dropna = dropna

self._grouper_deprecated = None
self._indexer_deprecated = None
self._obj_deprecated = None
self._gpr_index = None
self.obj = None
self.indexer = None
self.binner = None
self._grouper = None
self._indexer = None

@final
@property
def ax(self) -> Index:
index = self._gpr_index
if index is None:
raise ValueError("_set_grouper must be called before ax is accessed")
return index

def _get_grouper(
self, obj: NDFrameT, validate: bool = True
) -> tuple[ops.BaseGrouper, NDFrameT]:
Expand All @@ -299,7 +291,7 @@ def _get_grouper(
-------
a tuple of grouper, obj (possibly sorted)
"""
obj, _ = self._set_grouper(obj)
obj, _, _ = self._set_grouper(obj)
grouper, _, obj = get_grouper(
obj,
[self.key],
Expand Down Expand Up @@ -335,17 +327,20 @@ def _set_grouper(
-------
NDFrame
Index
np.ndarray[np.intp] | None
"""
assert obj is not None

indexer = None

if self.key is not None and self.level is not None:
raise ValueError("The Grouper cannot specify both a key and a level!")

# Keep self._grouper value before overriding
if self._grouper is None:
# TODO: What are we assuming about subsequent calls?
self._grouper = gpr_index
self._indexer = self.indexer
self._indexer = self._indexer_deprecated

# the key must be a valid info item
if self.key is not None:
Expand Down Expand Up @@ -387,17 +382,53 @@ def _set_grouper(
if (self.sort or sort) and not ax.is_monotonic_increasing:
# use stable sort to support first, last, nth
# TODO: why does putting na_position="first" fix datetimelike cases?
indexer = self.indexer = ax.array.argsort(
indexer = self._indexer_deprecated = ax.array.argsort(
kind="mergesort", na_position="first"
)
ax = ax.take(indexer)
obj = obj.take(indexer, axis=self.axis)

# error: Incompatible types in assignment (expression has type
# "NDFrameT", variable has type "None")
self.obj = obj # type: ignore[assignment]
self._obj_deprecated = obj # type: ignore[assignment]
self._gpr_index = ax
return obj, ax
return obj, ax, indexer

@final
@property
def ax(self) -> Index:
warnings.warn(
f"{type(self).__name__}.ax is deprecated and will be removed in a "
"future version. Use Resampler.ax instead",
FutureWarning,
stacklevel=find_stack_level(),
)
index = self._gpr_index
if index is None:
raise ValueError("_set_grouper must be called before ax is accessed")
return index

@final
@property
def indexer(self):
warnings.warn(
f"{type(self).__name__}.indexer is deprecated and will be removed "
"in a future version. Use Resampler.indexer instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
return self._indexer_deprecated

@final
@property
def obj(self):
warnings.warn(
f"{type(self).__name__}.obj is deprecated and will be removed "
"in a future version. Use GroupBy.indexer instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
return self._obj_deprecated

@final
@property
Expand Down
8 changes: 4 additions & 4 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class Resampler(BaseGroupBy, PandasObject):
_timegrouper: TimeGrouper
binner: DatetimeIndex | TimedeltaIndex | PeriodIndex # depends on subclass
exclusions: frozenset[Hashable] = frozenset() # for SelectionMixin compat
_internal_names_set = set({"obj", "ax"})
_internal_names_set = set({"obj", "ax", "_indexer"})

# to the groupby descriptor
_attributes = [
Expand Down Expand Up @@ -163,7 +163,7 @@ def __init__(
self.group_keys = group_keys
self.as_index = True

self.obj, self.ax = self._timegrouper._set_grouper(
self.obj, self.ax, self._indexer = self._timegrouper._set_grouper(
self._convert_obj(obj), sort=True, gpr_index=gpr_index
)
self.binner, self.grouper = self._get_binner()
Expand Down Expand Up @@ -230,7 +230,7 @@ def _get_binner(self):
"""
binner, bins, binlabels = self._get_binner_for_time()
assert len(bins) == len(binlabels)
bin_grouper = BinGrouper(bins, binlabels, indexer=self._timegrouper.indexer)
bin_grouper = BinGrouper(bins, binlabels, indexer=self._indexer)
return binner, bin_grouper

@Substitution(
Expand Down Expand Up @@ -1674,7 +1674,7 @@ def _get_resampler(self, obj: NDFrame, kind=None) -> Resampler:
TypeError if incompatible axis

"""
_, ax = self._set_grouper(obj, gpr_index=None)
_, ax, indexer = self._set_grouper(obj, gpr_index=None)

if isinstance(ax, DatetimeIndex):
return DatetimeIndexResampler(
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/groupby/test_grouping.py
Original file line number Diff line number Diff line change
Expand Up @@ -1066,3 +1066,16 @@ def test_grouper_groups():
with tm.assert_produces_warning(FutureWarning, match=msg):
res = grper.grouper
assert res is gb.grouper

msg = "Grouper.obj is deprecated and will be removed"
with tm.assert_produces_warning(FutureWarning, match=msg):
res = grper.obj
assert res is gb.obj

msg = "Use Resampler.ax instead"
with tm.assert_produces_warning(FutureWarning, match=msg):
grper.ax

msg = "Grouper.indexer is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
grper.indexer