diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 97b10e532c9de..31c1c2a638376 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -156,6 +156,48 @@ def asfreq(self, freq, method=None, how=None): from pandas.tseries.resample import asfreq return asfreq(self, freq, method=method, how=how) + def at_time(self, time, asof=False): + """ + Select values at particular time of day (e.g. 9:30AM) + + Parameters + ---------- + time : datetime.time or string + + Returns + ------- + values_at_time : type of caller + """ + try: + indexer = self.index.indexer_at_time(time, asof=asof) + return self.take(indexer) + except AttributeError: + raise TypeError('Index must be DatetimeIndex') + + def between_time(self, start_time, end_time, include_start=True, + include_end=True): + """ + Select values between particular times of the day (e.g., 9:00-9:30 AM) + + Parameters + ---------- + start_time : datetime.time or string + end_time : datetime.time or string + include_start : boolean, default True + include_end : boolean, default True + + Returns + ------- + values_between_time : type of caller + """ + try: + indexer = self.index.indexer_between_time( + start_time, end_time, include_start=include_start, + include_end=include_end) + return self.take(indexer) + except AttributeError: + raise TypeError('Index must be DatetimeIndex') + def resample(self, rule, how=None, axis=0, fill_method=None, closed='right', label='right', convention=None, kind=None, loffset=None, limit=None, base=0): diff --git a/pandas/core/series.py b/pandas/core/series.py index 7a7fc7159ecb4..b9c2e4c1cbb81 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -2921,42 +2921,6 @@ def _repr_footer(self): namestr = "Name: %s, " % str(self.name) if self.name is not None else "" return '%s%sLength: %d' % (freqstr, namestr, len(self)) - def at_time(self, time, asof=False): - """ - Select values at particular time of day (e.g. 9:30AM) - - Parameters - ---------- - time : datetime.time or string - - Returns - ------- - values_at_time : TimeSeries - """ - indexer = self.index.indexer_at_time(time, asof=asof) - return self.take(indexer) - - def between_time(self, start_time, end_time, include_start=True, - include_end=True): - """ - Select values between particular times of the day (e.g., 9:00-9:30 AM) - - Parameters - ---------- - start_time : datetime.time or string - end_time : datetime.time or string - include_start : boolean, default True - include_end : boolean, default True - - Returns - ------- - values_between_time : TimeSeries - """ - indexer = self.index.indexer_between_time( - start_time, end_time, include_start=include_start, - include_end=include_end) - return self.take(indexer) - def to_timestamp(self, freq=None, how='start', copy=True): """ Cast to datetimeindex of timestamps, at *beginning* of period diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py index 7507f3e4d66ee..19aa11baf2422 100644 --- a/pandas/tseries/tests/test_timeseries.py +++ b/pandas/tseries/tests/test_timeseries.py @@ -853,6 +853,36 @@ def test_at_time(self): rs = ts.at_time('16:00') self.assert_(len(rs) == 0) + def test_at_time_frame(self): + rng = date_range('1/1/2000', '1/5/2000', freq='5min') + ts = DataFrame(np.random.randn(len(rng), 2), index=rng) + rs = ts.at_time(rng[1]) + self.assert_((rs.index.hour == rng[1].hour).all()) + self.assert_((rs.index.minute == rng[1].minute).all()) + self.assert_((rs.index.second == rng[1].second).all()) + + result = ts.at_time('9:30') + expected = ts.at_time(time(9, 30)) + assert_frame_equal(result, expected) + + result = ts.ix[time(9, 30)] + expected = ts.ix[(rng.hour == 9) & (rng.minute == 30)] + + assert_frame_equal(result, expected) + + # midnight, everything + rng = date_range('1/1/2000', '1/31/2000') + ts = DataFrame(np.random.randn(len(rng), 3), index=rng) + + result = ts.at_time(time(0, 0)) + assert_frame_equal(result, ts) + + # time doesn't exist + rng = date_range('1/1/2012', freq='23Min', periods=384) + ts = DataFrame(np.random.randn(len(rng), 2), rng) + rs = ts.at_time('16:00') + self.assert_(len(rs) == 0) + def test_between_time(self): rng = date_range('1/1/2000', '1/5/2000', freq='5min') ts = Series(np.random.randn(len(rng)), index=rng) @@ -913,6 +943,66 @@ def test_between_time(self): else: self.assert_((t < etime) or (t >= stime)) + def test_between_time_frame(self): + rng = date_range('1/1/2000', '1/5/2000', freq='5min') + ts = DataFrame(np.random.randn(len(rng), 2), index=rng) + stime = time(0, 0) + etime = time(1, 0) + + close_open = itertools.product([True, False], [True, False]) + for inc_start, inc_end in close_open: + filtered = ts.between_time(stime, etime, inc_start, inc_end) + exp_len = 13 * 4 + 1 + if not inc_start: + exp_len -= 5 + if not inc_end: + exp_len -= 4 + + self.assert_(len(filtered) == exp_len) + for rs in filtered.index: + t = rs.time() + if inc_start: + self.assert_(t >= stime) + else: + self.assert_(t > stime) + + if inc_end: + self.assert_(t <= etime) + else: + self.assert_(t < etime) + + result = ts.between_time('00:00', '01:00') + expected = ts.between_time(stime, etime) + assert_frame_equal(result, expected) + + #across midnight + rng = date_range('1/1/2000', '1/5/2000', freq='5min') + ts = DataFrame(np.random.randn(len(rng), 2), index=rng) + stime = time(22, 0) + etime = time(9, 0) + + close_open = itertools.product([True, False], [True, False]) + for inc_start, inc_end in close_open: + filtered = ts.between_time(stime, etime, inc_start, inc_end) + exp_len = (12 * 11 + 1) * 4 + 1 + if not inc_start: + exp_len -= 4 + if not inc_end: + exp_len -= 4 + + self.assert_(len(filtered) == exp_len) + for rs in filtered.index: + t = rs.time() + if inc_start: + self.assert_((t >= stime) or (t <= etime)) + else: + self.assert_((t > stime) or (t <= etime)) + + if inc_end: + self.assert_((t <= etime) or (t >= stime)) + else: + self.assert_((t < etime) or (t >= stime)) + def test_dti_constructor_preserve_dti_freq(self): rng = date_range('1/1/2000', '1/2/2000', freq='5min')