Skip to content

Commit 0a6a3f6

Browse files
committed
CLN: move PeriodIndex binning code to TimeGrouper
Simplifies PeriodIndexResampler and makes it more similar to Resampler, DatetimeIndexResampler and TimedeltaIndexResampler.
1 parent 3b80ed3 commit 0a6a3f6

File tree

2 files changed

+32
-45
lines changed

2 files changed

+32
-45
lines changed

pandas/core/resample.py

+32-38
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pandas.core.indexes.datetimes import DatetimeIndex, date_range
1414
from pandas.core.indexes.timedeltas import TimedeltaIndex
1515
from pandas.tseries.offsets import DateOffset, Tick, Day, _delta_to_nanoseconds
16-
from pandas.core.indexes.period import PeriodIndex, period_range
16+
from pandas.core.indexes.period import PeriodIndex
1717
import pandas.core.common as com
1818
import pandas.core.algorithms as algos
1919

@@ -793,6 +793,11 @@ class PeriodIndexResampler(DatetimeIndexResampler):
793793
def _resampler_for_grouping(self):
794794
return PeriodIndexResamplerGroupby
795795

796+
def _get_binner_for_time(self):
797+
if self.kind == 'timestamp':
798+
return super(PeriodIndexResampler, self)._get_binner_for_time()
799+
return self.groupby._get_period_bins(self.ax)
800+
796801
def _convert_obj(self, obj):
797802
obj = super(PeriodIndexResampler, self)._convert_obj(obj)
798803

@@ -817,29 +822,6 @@ def _convert_obj(self, obj):
817822

818823
return obj
819824

820-
def aggregate(self, arg, *args, **kwargs):
821-
result, how = self._aggregate(arg, *args, **kwargs)
822-
if result is None:
823-
result = self._downsample(arg, *args, **kwargs)
824-
825-
result = self._apply_loffset(result)
826-
return result
827-
828-
agg = aggregate
829-
830-
def _get_new_index(self):
831-
""" return our new index """
832-
ax = self.ax
833-
834-
if len(ax) == 0:
835-
values = []
836-
else:
837-
start = ax[0].asfreq(self.freq, how=self.convention)
838-
end = ax[-1].asfreq(self.freq, how='end')
839-
values = period_range(start, end, freq=self.freq).asi8
840-
841-
return ax._shallow_copy(values, freq=self.freq)
842-
843825
def _downsample(self, how, **kwargs):
844826
"""
845827
Downsample the cython defined function
@@ -857,21 +839,9 @@ def _downsample(self, how, **kwargs):
857839
how = self._is_cython_func(how) or how
858840
ax = self.ax
859841

860-
new_index = self._get_new_index()
861-
862-
# Start vs. end of period
863-
memb = ax.asfreq(self.freq, how=self.convention)
864-
865842
if is_subperiod(ax.freq, self.freq):
866843
# Downsampling
867-
if len(new_index) == 0:
868-
bins = []
869-
else:
870-
i8 = memb.asi8
871-
rng = np.arange(i8[0], i8[-1] + 1)
872-
bins = memb.searchsorted(rng, side='right')
873-
grouper = BinGrouper(bins, new_index)
874-
return self._groupby_and_aggregate(how, grouper=grouper)
844+
return self._groupby_and_aggregate(how, grouper=self.grouper)
875845
elif is_superperiod(ax.freq, self.freq):
876846
return self.asfreq()
877847
elif ax.freq == self.freq:
@@ -905,9 +875,10 @@ def _upsample(self, method, limit=None, fill_value=None):
905875
return super(PeriodIndexResampler, self)._upsample(
906876
method, limit=limit, fill_value=fill_value)
907877

878+
self._set_binner()
908879
ax = self.ax
909880
obj = self.obj
910-
new_index = self._get_new_index()
881+
new_index = self.binner
911882

912883
# Start vs. end of period
913884
memb = ax.asfreq(self.freq, how=self.convention)
@@ -1269,6 +1240,29 @@ def _get_time_period_bins(self, ax):
12691240

12701241
return binner, bins, labels
12711242

1243+
def _get_period_bins(self, ax):
1244+
if not isinstance(ax, PeriodIndex):
1245+
raise TypeError('axis must be a PeriodIndex, but got '
1246+
'an instance of %r' % type(ax).__name__)
1247+
1248+
if not len(ax):
1249+
binner = labels = PeriodIndex(
1250+
data=[], freq=self.freq, name=ax.name)
1251+
return binner, [], labels
1252+
1253+
start = ax[0].asfreq(self.freq, how=self.convention)
1254+
end = ax[-1].asfreq(self.freq, how='end')
1255+
1256+
labels = binner = PeriodIndex(start=start, end=end,
1257+
freq=self.freq, name=ax.name)
1258+
1259+
memb = ax.asfreq(self.freq, how=self.convention)
1260+
i8 = memb.asi8
1261+
rng = np.arange(i8[0], i8[-1] + 1)
1262+
bins = memb.searchsorted(rng, side='right')
1263+
1264+
return binner, bins, labels
1265+
12721266

12731267
def _take_new_index(obj, indexer, new_index, axis=0):
12741268
from pandas.core.api import Series, DataFrame

pandas/tests/test_resample.py

-7
Original file line numberDiff line numberDiff line change
@@ -3088,13 +3088,6 @@ def test_fails_on_no_datetime_index(self):
30883088
"instance of %r" % name):
30893089
df.groupby(TimeGrouper('D'))
30903090

3091-
# PeriodIndex gives a specific error message
3092-
df = DataFrame({'a': np.random.randn(n)}, index=tm.makePeriodIndex(n))
3093-
with tm.assert_raises_regex(TypeError,
3094-
"axis must be a DatetimeIndex, but "
3095-
"got an instance of 'PeriodIndex'"):
3096-
df.groupby(TimeGrouper('D'))
3097-
30983091
def test_aaa_group_order(self):
30993092
# GH 12840
31003093
# check TimeGrouper perform stable sorts

0 commit comments

Comments
 (0)