Skip to content

ENH: at_time and between_time for DataFrame #2131 #2149

New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
36 changes: 0 additions & 36 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
90 changes: 90 additions & 0 deletions pandas/tseries/tests/test_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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')

Expand Down