Skip to content

Commit 9deda9e

Browse files
committed
API: change resample to infer correct closed and label value by default #2363
1 parent 5fdae30 commit 9deda9e

File tree

3 files changed

+43
-26
lines changed

3 files changed

+43
-26
lines changed

pandas/core/generic.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def between_time(self, start_time, end_time, include_start=True,
203203
raise TypeError('Index must be DatetimeIndex')
204204

205205
def resample(self, rule, how=None, axis=0, fill_method=None,
206-
closed='right', label='right', convention='start',
206+
closed=None, label=None, convention='start',
207207
kind=None, loffset=None, limit=None, base=0):
208208
"""
209209
Convenience method for frequency conversion and resampling of regular
@@ -216,9 +216,9 @@ def resample(self, rule, how=None, axis=0, fill_method=None,
216216
downsampling
217217
fill_method : string, fill_method for upsampling, default None
218218
axis : int, optional, default 0
219-
closed : {'right', 'left'}, default 'right'
219+
closed : {'right', 'left'}, default None
220220
Which side of bin interval is closed
221-
label : {'right', 'left'}, default 'right'
221+
label : {'right', 'left'}, default None
222222
Which bin edge label to label bucket with
223223
convention : {'start', 'end', 's', 'e'}
224224
loffset : timedelta

pandas/tseries/resample.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,26 @@ class TimeGrouper(CustomGrouper):
3535
Use begin, end, nperiods to generate intervals that cannot be derived
3636
directly from the associated object
3737
"""
38-
def __init__(self, freq='Min', closed='right', label='right', how='mean',
38+
def __init__(self, freq='Min', closed=None, label=None, how='mean',
3939
nperiods=None, axis=0,
4040
fill_method=None, limit=None, loffset=None, kind=None,
4141
convention=None, base=0):
4242
self.freq = to_offset(freq)
43+
44+
end_types = set(['M', 'A', 'Q', 'BM', 'BA', 'BQ', 'W'])
45+
rule = self.freq.rule_code
46+
if (rule in end_types or
47+
('-' in rule and rule[:rule.find('-')])):
48+
if closed is None:
49+
closed = 'right'
50+
if label is None:
51+
label = 'right'
52+
else:
53+
if closed is None:
54+
closed = 'left'
55+
if label is None:
56+
label = 'left'
57+
4358
self.closed = closed
4459
self.label = label
4560
self.nperiods = nperiods

pandas/tseries/tests/test_resample.py

+24-22
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ def test_resample_basic(self):
9999

100100
s = self.series
101101
result = s.resample('5Min', how='last')
102-
grouper = TimeGrouper(Minute(5), closed='right', label='right')
102+
grouper = TimeGrouper(Minute(5), closed='left', label='left')
103103
expect = s.groupby(grouper).agg(lambda x: x[-1])
104104
assert_series_equal(result, expect)
105105

106+
def test_resample_basic_from_daily(self):
106107
# from daily
107108
dti = DatetimeIndex(start=datetime(2005,1,1), end=datetime(2005,1,10),
108109
freq='D', name='index')
@@ -150,11 +151,11 @@ def test_resample_basic(self):
150151

151152
# to biz day
152153
result = s.resample('B', how='last')
153-
self.assertEquals(len(result), 6)
154-
self.assert_((result.index.dayofweek == [0,1,2,3,4,0]).all())
155-
self.assertEquals(result.irow(0), s['1/3/2005'])
156-
self.assertEquals(result.irow(1), s['1/4/2005'])
157-
self.assertEquals(result.irow(5), s['1/10/2005'])
154+
self.assertEquals(len(result), 7)
155+
self.assert_((result.index.dayofweek == [4,0,1,2,3,4,0]).all())
156+
self.assertEquals(result.irow(0), s['1/2/2005'])
157+
self.assertEquals(result.irow(1), s['1/3/2005'])
158+
self.assertEquals(result.irow(5), s['1/9/2005'])
158159
self.assert_(result.index.name == 'index')
159160

160161
def test_resample_frame_basic(self):
@@ -234,30 +235,30 @@ def test_upsample_with_limit(self):
234235
def test_resample_ohlc(self):
235236
s = self.series
236237

237-
grouper = TimeGrouper(Minute(5), closed='right', label='right')
238+
grouper = TimeGrouper(Minute(5))
238239
expect = s.groupby(grouper).agg(lambda x: x[-1])
239240
result = s.resample('5Min', how='ohlc')
240241

241242
self.assertEquals(len(result), len(expect))
242243
self.assertEquals(len(result.columns), 4)
243244

244-
xs = result.irow(-1)
245-
self.assertEquals(xs['open'], s[-5])
246-
self.assertEquals(xs['high'], s[-5:].max())
247-
self.assertEquals(xs['low'], s[-5:].min())
248-
self.assertEquals(xs['close'], s[-1])
245+
xs = result.irow(-2)
246+
self.assertEquals(xs['open'], s[-6])
247+
self.assertEquals(xs['high'], s[-6:-1].max())
248+
self.assertEquals(xs['low'], s[-6:-1].min())
249+
self.assertEquals(xs['close'], s[-2])
249250

250-
xs = result.irow(1)
251-
self.assertEquals(xs['open'], s[1])
252-
self.assertEquals(xs['high'], s[1:6].max())
253-
self.assertEquals(xs['low'], s[1:6].min())
254-
self.assertEquals(xs['close'], s[5])
251+
xs = result.irow(0)
252+
self.assertEquals(xs['open'], s[0])
253+
self.assertEquals(xs['high'], s[:5].max())
254+
self.assertEquals(xs['low'], s[:5].min())
255+
self.assertEquals(xs['close'], s[4])
255256

256257
def test_resample_reresample(self):
257258
dti = DatetimeIndex(start=datetime(2005,1,1), end=datetime(2005,1,10),
258259
freq='D')
259260
s = Series(np.random.rand(len(dti)), dti)
260-
bs = s.resample('B')
261+
bs = s.resample('B', closed='right', label='right')
261262
result = bs.resample('8H')
262263
self.assertEquals(len(result), 22)
263264
self.assert_(isinstance(result.index.freq, offsets.DateOffset))
@@ -296,7 +297,8 @@ def _ohlc(group):
296297
freq='10s')
297298
ts = Series(np.random.randn(len(rng)), index=rng)
298299

299-
resampled = ts.resample('5min', how='ohlc')
300+
resampled = ts.resample('5min', how='ohlc', closed='right',
301+
label='right')
300302

301303
self.assert_((resampled.ix['1/1/2000 00:00'] == ts[0]).all())
302304

@@ -394,7 +396,7 @@ def test_resample_base(self):
394396
ts = Series(np.random.randn(len(rng)), index=rng)
395397

396398
resampled = ts.resample('5min', base=2)
397-
exp_rng = date_range('1/1/2000 00:02:00', '1/1/2000 02:02',
399+
exp_rng = date_range('12/31/1999 23:57:00', '1/1/2000 01:57',
398400
freq='5min')
399401
self.assert_(resampled.index.equals(exp_rng))
400402

@@ -785,7 +787,7 @@ def test_resample_irregular_sparse(self):
785787
dr = date_range(start='1/1/2012', freq='5min', periods=1000)
786788
s = Series(np.array(100), index=dr)
787789
# subset the data.
788-
subset = s[:'2012-01-04 07:00']
790+
subset = s[:'2012-01-04 06:55']
789791

790792
result = subset.resample('10min', how=len)
791793
expected = s.resample('10min', how=len).ix[result.index]
@@ -828,7 +830,7 @@ def test_resample_tz_localized(self):
828830
tz='Australia/Sydney')
829831
s = Series([1,2], index=idx)
830832

831-
result = s.resample('D')
833+
result = s.resample('D', closed='right', label='right')
832834
ex_index = date_range('2001-09-21', periods=1, freq='D',
833835
tz='Australia/Sydney')
834836
expected = Series([1.5], index=ex_index)

0 commit comments

Comments
 (0)