diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 7705cbd9bfd11..86f783c83901f 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1,10 +1,12 @@ # pylint: disable=W0231 +from datetime import timedelta import numpy as np from pandas.core.common import save, load from pandas.core.index import MultiIndex from pandas.tseries.index import DatetimeIndex +from pandas.tseries.offsets import DateOffset #------------------------------------------------------------------------------- # Picklable mixin @@ -136,7 +138,8 @@ def groupby(self, by=None, axis=0, level=None, as_index=True, sort=True, sort=sort, group_keys=group_keys) def resample(self, rule, how='mean', axis=0, as_index=True, - fill_method=None, closed='right', label='right', kind=None): + fill_method=None, closed='right', label='right', kind=None, + loffset=None): """ Convenience method for frequency conversion and resampling of regular time-series data. @@ -152,6 +155,8 @@ def resample(self, rule, how='mean', axis=0, as_index=True, label : {'right', 'left'}, default 'right' Which bin edge label to label bucket with as_index : see synonymous argument of groupby + loffset : timedelta + Adjust the resampled time labels """ from pandas.tseries.resample import TimeGrouper @@ -171,6 +176,9 @@ def resample(self, rule, how='mean', axis=0, as_index=True, # upsampling result = self.reindex(grouper.binner[1:], method=fill_method) + if isinstance(loffset, (DateOffset, timedelta)): + if len(result.index) > 0: + result.index = result.index + loffset return result def first(self, offset): diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index d2ef630d09417..86af120b7af4e 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -221,8 +221,13 @@ def test_add(self): tm.assert_contains_all(self.strIndex, secondCat) tm.assert_contains_all(self.dateIndex, firstCat) + def test_timedelta(self): # this is valid too shifted = self.dateIndex + timedelta(1) + back = shifted + timedelta(-1) + self.assert_(tm.equalContents(self.dateIndex, back)) + self.assertEqual(shifted.freq, self.dateIndex.freq) + self.assertEqual(shifted.freq, back.freq) def test_append_multiple(self): index = Index(['a', 'b', 'c', 'd', 'e', 'f']) diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index 1cae0a8e91fd9..cdc031a3b4d76 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -150,7 +150,6 @@ class DatetimeIndex(Int64Index): __le__ = _dt_index_cmp('__le__') __ge__ = _dt_index_cmp('__ge__') - __add__ = _dt_index_op('__add__') __sub__ = _dt_index_op('__sub__') # structured array cache for datetime fields diff --git a/pandas/tseries/tests/test_resample.py b/pandas/tseries/tests/test_resample.py index c00cf242e39d2..2451bbeeddeb7 100644 --- a/pandas/tseries/tests/test_resample.py +++ b/pandas/tseries/tests/test_resample.py @@ -1,11 +1,11 @@ -from datetime import datetime +from datetime import datetime, timedelta import numpy as np from pandas import Series, DataFrame, isnull, notnull from pandas.tseries.index import date_range -from pandas.tseries.offsets import Minute +from pandas.tseries.offsets import Minute, bday from pandas.tseries.period import period_range from pandas.tseries.resample import DatetimeIndex, TimeGrouper import pandas.tseries.offsets as offsets @@ -133,6 +133,26 @@ def test_resample_basic(self): self.assertEquals(result.irow(1), s['1/4/2005']) self.assertEquals(result.irow(5), s['1/10/2005']) + def test_resample_loffset(self): + rng = date_range('1/1/2000 00:00:00', '1/1/2000 00:13:00', freq='min') + s = Series(np.random.randn(14), index=rng) + result = s.resample('5min', how='mean', closed='right', label='right', + loffset=timedelta(minutes=1)) + idx = date_range('1/1/2000', periods=4, freq='5min') + expected = Series([s[0], s[1:6].mean(), s[6:11].mean(), s[11:].mean()], + index=idx + timedelta(minutes=1)) + assert_series_equal(result, expected) + + # from daily + dti = DatetimeIndex(start=datetime(2005,1,1), end=datetime(2005,1,10), + freq='D') + ser = Series(np.random.rand(len(dti)), dti) + + # to weekly + result = ser.resample('w-sun', how='last') + expected = ser.resample('w-sun', how='last', loffset=-bday) + self.assertEqual(result.index[0] - bday, expected.index[0]) + def test_resample_upsample(self): # from daily dti = DatetimeIndex(start=datetime(2005,1,1), end=datetime(2005,1,10), diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 50a3bdd6577f9..9e4475cb62339 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -163,10 +163,6 @@ def makeFloatIndex(k): values = sorted(np.random.random_sample(k)) - np.random.random_sample(1) return Index(values * (10 ** np.random.randint(0, 9))) -def makeDateIndex(k): - dates = list(bdate_range(datetime(2000, 1, 1), periods=k)) - return Index(dates) - def makeFloatSeries(): index = makeStringIndex(N) return Series(randn(N), index=index)