Skip to content

Commit e8cff23

Browse files
committed
Merge remote branch 'chang/resample-interval'
* chang/resample-interval: TST: more tests for resample closed and label inference API: change resample to infer correct closed and label value by default #2363
2 parents 76d6340 + ce604af commit e8cff23

File tree

3 files changed

+72
-27
lines changed

3 files changed

+72
-27
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('-')] in end_types)):
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

+53-23
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
import unittest
1717
import nose
1818

19-
from pandas.util.testing import assert_series_equal, assert_almost_equal
19+
from pandas.util.testing import (assert_series_equal, assert_almost_equal,
20+
assert_frame_equal)
2021
import pandas.util.testing as tm
2122

2223
bday = BDay()
@@ -99,10 +100,11 @@ def test_resample_basic(self):
99100

100101
s = self.series
101102
result = s.resample('5Min', how='last')
102-
grouper = TimeGrouper(Minute(5), closed='right', label='right')
103+
grouper = TimeGrouper(Minute(5), closed='left', label='left')
103104
expect = s.groupby(grouper).agg(lambda x: x[-1])
104105
assert_series_equal(result, expect)
105106

107+
def test_resample_basic_from_daily(self):
106108
# from daily
107109
dti = DatetimeIndex(start=datetime(2005,1,1), end=datetime(2005,1,10),
108110
freq='D', name='index')
@@ -150,11 +152,11 @@ def test_resample_basic(self):
150152

151153
# to biz day
152154
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'])
155+
self.assertEquals(len(result), 7)
156+
self.assert_((result.index.dayofweek == [4,0,1,2,3,4,0]).all())
157+
self.assertEquals(result.irow(0), s['1/2/2005'])
158+
self.assertEquals(result.irow(1), s['1/3/2005'])
159+
self.assertEquals(result.irow(5), s['1/9/2005'])
158160
self.assert_(result.index.name == 'index')
159161

160162
def test_resample_frame_basic(self):
@@ -234,30 +236,30 @@ def test_upsample_with_limit(self):
234236
def test_resample_ohlc(self):
235237
s = self.series
236238

237-
grouper = TimeGrouper(Minute(5), closed='right', label='right')
239+
grouper = TimeGrouper(Minute(5))
238240
expect = s.groupby(grouper).agg(lambda x: x[-1])
239241
result = s.resample('5Min', how='ohlc')
240242

241243
self.assertEquals(len(result), len(expect))
242244
self.assertEquals(len(result.columns), 4)
243245

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])
246+
xs = result.irow(-2)
247+
self.assertEquals(xs['open'], s[-6])
248+
self.assertEquals(xs['high'], s[-6:-1].max())
249+
self.assertEquals(xs['low'], s[-6:-1].min())
250+
self.assertEquals(xs['close'], s[-2])
249251

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])
252+
xs = result.irow(0)
253+
self.assertEquals(xs['open'], s[0])
254+
self.assertEquals(xs['high'], s[:5].max())
255+
self.assertEquals(xs['low'], s[:5].min())
256+
self.assertEquals(xs['close'], s[4])
255257

256258
def test_resample_reresample(self):
257259
dti = DatetimeIndex(start=datetime(2005,1,1), end=datetime(2005,1,10),
258260
freq='D')
259261
s = Series(np.random.rand(len(dti)), dti)
260-
bs = s.resample('B')
262+
bs = s.resample('B', closed='right', label='right')
261263
result = bs.resample('8H')
262264
self.assertEquals(len(result), 22)
263265
self.assert_(isinstance(result.index.freq, offsets.DateOffset))
@@ -296,7 +298,8 @@ def _ohlc(group):
296298
freq='10s')
297299
ts = Series(np.random.randn(len(rng)), index=rng)
298300

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

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

@@ -394,7 +397,7 @@ def test_resample_base(self):
394397
ts = Series(np.random.randn(len(rng)), index=rng)
395398

396399
resampled = ts.resample('5min', base=2)
397-
exp_rng = date_range('1/1/2000 00:02:00', '1/1/2000 02:02',
400+
exp_rng = date_range('12/31/1999 23:57:00', '1/1/2000 01:57',
398401
freq='5min')
399402
self.assert_(resampled.index.equals(exp_rng))
400403

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

790793
result = subset.resample('10min', how=len)
791794
expected = s.resample('10min', how=len).ix[result.index]
@@ -828,7 +831,7 @@ def test_resample_tz_localized(self):
828831
tz='Australia/Sydney')
829832
s = Series([1,2], index=idx)
830833

831-
result = s.resample('D')
834+
result = s.resample('D', closed='right', label='right')
832835
ex_index = date_range('2001-09-21', periods=1, freq='D',
833836
tz='Australia/Sydney')
834837
expected = Series([1.5], index=ex_index)
@@ -892,6 +895,33 @@ def test_resample_weekly_bug_1726(self):
892895

893896
# assert_series_equal(result, expected)
894897

898+
def test_default_right_closed_label(self):
899+
end_freq = ['D', 'Q', 'M', 'D']
900+
end_types = ['M', 'A', 'Q', 'W']
901+
902+
for from_freq, to_freq in zip(end_freq, end_types):
903+
idx = DatetimeIndex(start='8/15/2012', periods=100,
904+
freq=from_freq)
905+
df = DataFrame(np.random.randn(len(idx), 2), idx)
906+
907+
resampled = df.resample(to_freq)
908+
assert_frame_equal(resampled, df.resample(to_freq, closed='right',
909+
label='right'))
910+
911+
def test_default_left_closed_label(self):
912+
others = ['MS', 'AS', 'QS', 'D', 'H']
913+
others_freq = ['D', 'Q', 'M', 'H', 'T']
914+
915+
for from_freq, to_freq in zip(others_freq, others):
916+
idx = DatetimeIndex(start='8/15/2012', periods=100,
917+
freq=from_freq)
918+
df = DataFrame(np.random.randn(len(idx), 2), idx)
919+
920+
resampled = df.resample(to_freq)
921+
assert_frame_equal(resampled, df.resample(to_freq, closed='left',
922+
label='left'))
923+
924+
895925
class TestTimeGrouper(unittest.TestCase):
896926

897927
def setUp(self):

0 commit comments

Comments
 (0)