Skip to content

Commit 93a2d42

Browse files
author
tp
committed
Added repr string for Grouper and TimeGrouper
1 parent 458c1dc commit 93a2d42

File tree

4 files changed

+64
-1
lines changed

4 files changed

+64
-1
lines changed

pandas/core/groupby.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ class Grouper(object):
233233
234234
>>> df.groupby(Grouper(level='date', freq='60s', axis=1))
235235
"""
236+
_attributes = collections.OrderedDict((('key', None), ('level', None),
237+
('freq', None), ('axis', 0),
238+
('sort', False)
239+
))
236240

237241
def __new__(cls, *args, **kwargs):
238242
if kwargs.get('freq') is not None:
@@ -333,6 +337,15 @@ def _set_grouper(self, obj, sort=False):
333337
def groups(self):
334338
return self.grouper.groups
335339

340+
def __repr__(self):
341+
defaults = self._attributes
342+
sd = self.__dict__
343+
attrs = collections.OrderedDict((k, sd[k]) for k, v in defaults.items()
344+
if k in sd and sd[k] != v)
345+
attrs = ", ".join("{}={!r}".format(k, v) for k, v in attrs.items())
346+
cls_name = self.__class__.__name__
347+
return "{}({})".format(cls_name, attrs)
348+
336349

337350
class GroupByPlot(PandasObject):
338351
"""

pandas/core/resample.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from datetime import timedelta
2+
import collections
23
import numpy as np
34
import warnings
45
import copy
@@ -1021,14 +1022,24 @@ class TimeGrouper(Grouper):
10211022
Use begin, end, nperiods to generate intervals that cannot be derived
10221023
directly from the associated object
10231024
"""
1025+
# _attributes is used in __repr__below
1026+
_attributes = Grouper._attributes.copy()
1027+
_attributes.update((('freq', 'Min'), ('closed', None), ('label', None),
1028+
('how', 'mean'), ('nperiods', None), ('axis', 0),
1029+
('fill_method', None), ('limit', None),
1030+
('loffset', None), ('kind', None),
1031+
('convention', None), ('base', 0),
1032+
('convention', 'e'), ('sort', True),
1033+
))
1034+
_end_types = {'M', 'A', 'Q', 'BM', 'BA', 'BQ', 'W'}
10241035

10251036
def __init__(self, freq='Min', closed=None, label=None, how='mean',
10261037
nperiods=None, axis=0,
10271038
fill_method=None, limit=None, loffset=None, kind=None,
10281039
convention=None, base=0, **kwargs):
10291040
freq = to_offset(freq)
10301041

1031-
end_types = set(['M', 'A', 'Q', 'BM', 'BA', 'BQ', 'W'])
1042+
end_types = self._end_types
10321043
rule = freq.rule_code
10331044
if (rule in end_types or
10341045
('-' in rule and rule[:rule.find('-')] in end_types)):
@@ -1043,6 +1054,7 @@ def __init__(self, freq='Min', closed=None, label=None, how='mean',
10431054
label = 'left'
10441055

10451056
self.closed = closed
1057+
self.freq = freq
10461058
self.label = label
10471059
self.nperiods = nperiods
10481060
self.kind = kind
@@ -1286,6 +1298,25 @@ def _get_period_bins(self, ax):
12861298

12871299
return binner, bins, labels
12881300

1301+
def __repr__(self):
1302+
defaults = self._attributes.copy()
1303+
end_types = self._end_types
1304+
rule = self.freq.rule_code
1305+
if (rule in end_types or
1306+
('-' in rule and rule[:rule.find('-')] in end_types)):
1307+
defaults.update(closed='right', label='right')
1308+
else:
1309+
defaults.update(closed='left', label='left')
1310+
1311+
sd = self.__dict__
1312+
attrs = collections.OrderedDict((k, sd[k]) for k, v in defaults.items()
1313+
if k in sd and sd[k] != v)
1314+
if 'freq' in attrs:
1315+
attrs['freq'] = attrs['freq'].freqstr
1316+
attrs = ", ".join("{}={!r}".format(k, v) for k, v in attrs.items())
1317+
cls_name = self.__class__.__name__
1318+
return "{}({})".format(cls_name, attrs)
1319+
12891320

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

pandas/tests/groupby/test_groupby.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ def test_grouper_index_types(self):
130130
df.index = list(reversed(df.index.tolist()))
131131
df.groupby(list('abcde')).apply(lambda x: x)
132132

133+
def test_grouper_repr(self):
134+
# Added in GH17727
135+
result = repr(pd.Grouper(key='A'))
136+
assert result == "Grouper(key='A')"
137+
138+
result = repr(pd.Grouper(key='key', freq='50Min', label='right'))
139+
cls_name_result, attrib_result = result.split('(')
140+
attrib_result = set(attrib_result.rstrip(')').split(', '))
141+
assert cls_name_result == 'TimeGrouper'
142+
assert attrib_result == {"key='key'", "label='right'", "freq='50T'"}
143+
133144
def test_grouper_multilevel_freq(self):
134145

135146
# GH 7885

pandas/tests/test_resample.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3157,6 +3157,14 @@ def setup_method(self, method):
31573157
self.ts = Series(np.random.randn(1000),
31583158
index=date_range('1/1/2000', periods=1000))
31593159

3160+
def test_timegrouper_repr(self):
3161+
# Added in GH17727
3162+
result = repr(TimeGrouper(key='key', freq='50Min', label='right'))
3163+
cls_name_result, attrib_result = result.split('(')
3164+
attrib_result = set(attrib_result.rstrip(')').split(', '))
3165+
assert cls_name_result == 'TimeGrouper'
3166+
assert attrib_result == {"key='key'", "label='right'", "freq='50T'"}
3167+
31603168
def test_apply(self):
31613169
with tm.assert_produces_warning(FutureWarning,
31623170
check_stacklevel=False):

0 commit comments

Comments
 (0)