Skip to content

Commit 016063e

Browse files
authored
DEPR: Grouper.ax, Grouper.obj, Grouper.indexer (#51206)
1 parent 590caa4 commit 016063e

File tree

4 files changed

+66
-19
lines changed

4 files changed

+66
-19
lines changed

doc/source/whatsnew/v2.0.0.rst

+3
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,9 @@ Deprecations
788788
- 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`)
789789
- Deprecated :meth:`Grouper.groups`, use :meth:`Groupby.groups` instead (:issue:`51182`)
790790
- Deprecated :meth:`Grouper.grouper`, use :meth:`Groupby.grouper` instead (:issue:`51182`)
791+
- Deprecated :meth:`Grouper.obj`, use :meth:`Groupby.obj` instead (:issue:`51206`)
792+
- Deprecated :meth:`Grouper.indexer`, use :meth:`Resampler.indexer` instead (:issue:`51206`)
793+
- Deprecated :meth:`Grouper.ax`, use :meth:`Resampler.ax` instead (:issue:`51206`)
791794
- Deprecated :meth:`Series.pad` in favor of :meth:`Series.ffill` (:issue:`33396`)
792795
- Deprecated :meth:`Series.backfill` in favor of :meth:`Series.bfill` (:issue:`33396`)
793796
- Deprecated :meth:`DataFrame.pad` in favor of :meth:`DataFrame.ffill` (:issue:`33396`)

pandas/core/groupby/grouper.py

+46-15
Original file line numberDiff line numberDiff line change
@@ -270,21 +270,13 @@ def __init__(
270270
self.dropna = dropna
271271

272272
self._grouper_deprecated = None
273+
self._indexer_deprecated = None
274+
self._obj_deprecated = None
273275
self._gpr_index = None
274-
self.obj = None
275-
self.indexer = None
276276
self.binner = None
277277
self._grouper = None
278278
self._indexer = None
279279

280-
@final
281-
@property
282-
def ax(self) -> Index:
283-
index = self._gpr_index
284-
if index is None:
285-
raise ValueError("_set_grouper must be called before ax is accessed")
286-
return index
287-
288280
def _get_grouper(
289281
self, obj: NDFrameT, validate: bool = True
290282
) -> tuple[ops.BaseGrouper, NDFrameT]:
@@ -299,7 +291,7 @@ def _get_grouper(
299291
-------
300292
a tuple of grouper, obj (possibly sorted)
301293
"""
302-
obj, _ = self._set_grouper(obj)
294+
obj, _, _ = self._set_grouper(obj)
303295
grouper, _, obj = get_grouper(
304296
obj,
305297
[self.key],
@@ -335,17 +327,20 @@ def _set_grouper(
335327
-------
336328
NDFrame
337329
Index
330+
np.ndarray[np.intp] | None
338331
"""
339332
assert obj is not None
340333

334+
indexer = None
335+
341336
if self.key is not None and self.level is not None:
342337
raise ValueError("The Grouper cannot specify both a key and a level!")
343338

344339
# Keep self._grouper value before overriding
345340
if self._grouper is None:
346341
# TODO: What are we assuming about subsequent calls?
347342
self._grouper = gpr_index
348-
self._indexer = self.indexer
343+
self._indexer = self._indexer_deprecated
349344

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

396391
# error: Incompatible types in assignment (expression has type
397392
# "NDFrameT", variable has type "None")
398-
self.obj = obj # type: ignore[assignment]
393+
self._obj_deprecated = obj # type: ignore[assignment]
399394
self._gpr_index = ax
400-
return obj, ax
395+
return obj, ax, indexer
396+
397+
@final
398+
@property
399+
def ax(self) -> Index:
400+
warnings.warn(
401+
f"{type(self).__name__}.ax is deprecated and will be removed in a "
402+
"future version. Use Resampler.ax instead",
403+
FutureWarning,
404+
stacklevel=find_stack_level(),
405+
)
406+
index = self._gpr_index
407+
if index is None:
408+
raise ValueError("_set_grouper must be called before ax is accessed")
409+
return index
410+
411+
@final
412+
@property
413+
def indexer(self):
414+
warnings.warn(
415+
f"{type(self).__name__}.indexer is deprecated and will be removed "
416+
"in a future version. Use Resampler.indexer instead.",
417+
FutureWarning,
418+
stacklevel=find_stack_level(),
419+
)
420+
return self._indexer_deprecated
421+
422+
@final
423+
@property
424+
def obj(self):
425+
warnings.warn(
426+
f"{type(self).__name__}.obj is deprecated and will be removed "
427+
"in a future version. Use GroupBy.indexer instead.",
428+
FutureWarning,
429+
stacklevel=find_stack_level(),
430+
)
431+
return self._obj_deprecated
401432

402433
@final
403434
@property

pandas/core/resample.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class Resampler(BaseGroupBy, PandasObject):
130130
_timegrouper: TimeGrouper
131131
binner: DatetimeIndex | TimedeltaIndex | PeriodIndex # depends on subclass
132132
exclusions: frozenset[Hashable] = frozenset() # for SelectionMixin compat
133-
_internal_names_set = set({"obj", "ax"})
133+
_internal_names_set = set({"obj", "ax", "_indexer"})
134134

135135
# to the groupby descriptor
136136
_attributes = [
@@ -163,7 +163,7 @@ def __init__(
163163
self.group_keys = group_keys
164164
self.as_index = True
165165

166-
self.obj, self.ax = self._timegrouper._set_grouper(
166+
self.obj, self.ax, self._indexer = self._timegrouper._set_grouper(
167167
self._convert_obj(obj), sort=True, gpr_index=gpr_index
168168
)
169169
self.binner, self.grouper = self._get_binner()
@@ -230,7 +230,7 @@ def _get_binner(self):
230230
"""
231231
binner, bins, binlabels = self._get_binner_for_time()
232232
assert len(bins) == len(binlabels)
233-
bin_grouper = BinGrouper(bins, binlabels, indexer=self._timegrouper.indexer)
233+
bin_grouper = BinGrouper(bins, binlabels, indexer=self._indexer)
234234
return binner, bin_grouper
235235

236236
@Substitution(
@@ -1674,7 +1674,7 @@ def _get_resampler(self, obj: NDFrame, kind=None) -> Resampler:
16741674
TypeError if incompatible axis
16751675
16761676
"""
1677-
_, ax = self._set_grouper(obj, gpr_index=None)
1677+
_, ax, indexer = self._set_grouper(obj, gpr_index=None)
16781678

16791679
if isinstance(ax, DatetimeIndex):
16801680
return DatetimeIndexResampler(

pandas/tests/groupby/test_grouping.py

+13
Original file line numberDiff line numberDiff line change
@@ -1066,3 +1066,16 @@ def test_grouper_groups():
10661066
with tm.assert_produces_warning(FutureWarning, match=msg):
10671067
res = grper.grouper
10681068
assert res is gb.grouper
1069+
1070+
msg = "Grouper.obj is deprecated and will be removed"
1071+
with tm.assert_produces_warning(FutureWarning, match=msg):
1072+
res = grper.obj
1073+
assert res is gb.obj
1074+
1075+
msg = "Use Resampler.ax instead"
1076+
with tm.assert_produces_warning(FutureWarning, match=msg):
1077+
grper.ax
1078+
1079+
msg = "Grouper.indexer is deprecated"
1080+
with tm.assert_produces_warning(FutureWarning, match=msg):
1081+
grper.indexer

0 commit comments

Comments
 (0)