Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

ENH: at_time and between_time for DataFrame #2131 #2149

Closed
wants to merge 1 commit into
from
Jump to file or symbol
Failed to load files and symbols.
+132 −36
Split
View
@@ -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):
View
@@ -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
@@ -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')