Skip to content
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: 33 additions & 9 deletions pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,30 @@ def _wrap_joined_index(self, joined, other):
name = self.name if self.name == other.name else None
return Index(joined, name=name)

def slice_indexer(self, start=None, end=None, step=None):
"""
For an ordered Index, compute the slice indexer for input labels and
step

Parameters
----------
start : label, default None
If None, defaults to the beginning
end : label, default None
If None, defaults to the end
step : int, default None

Returns
-------
indexer : ndarray or slice

Notes
-----
This function assumes that the data is sorted, so use at your own peril
"""
start_slice, end_slice = self.slice_locs(start, end)
return slice(start_slice, end_slice, step)

def slice_locs(self, start=None, end=None):
"""
For an ordered Index, compute the slice locations for input labels
Expand All @@ -1125,27 +1149,27 @@ def slice_locs(self, start=None, end=None):
----------
start : label, default None
If None, defaults to the beginning
end : label
end : label, default None
If None, defaults to the end

Returns
-------
(begin, end) : (int, int)
(start, end) : (int, int)

Notes
-----
This function assumes that the data is sorted, so use at your own peril
"""
if start is None:
beg_slice = 0
start_slice = 0
else:
try:
beg_slice = self.get_loc(start)
if isinstance(beg_slice, slice):
beg_slice = beg_slice.start
start_slice = self.get_loc(start)
if isinstance(start_slice, slice):
start_slice = start_slice.start
except KeyError:
if self.is_monotonic:
beg_slice = self.searchsorted(start, side='left')
start_slice = self.searchsorted(start, side='left')
else:
raise

Expand All @@ -1164,7 +1188,7 @@ def slice_locs(self, start=None, end=None):
else:
raise

return beg_slice, end_slice
return start_slice, end_slice

def delete(self, loc):
"""
Expand Down Expand Up @@ -2106,7 +2130,7 @@ def slice_locs(self, start=None, end=None, strict=False):

Returns
-------
(begin, end) : (int, int)
(start, end) : (int, int)

Notes
-----
Expand Down
30 changes: 15 additions & 15 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,20 +462,19 @@ def _convert_to_indexer(self, obj, axis=0):
raise

if null_slice or position_slice:
slicer = obj
indexer = obj
else:
try:
i, j = labels.slice_locs(start, stop)
slicer = slice(i, j, obj.step)
indexer = labels.slice_indexer(start, stop, obj.step)
except Exception:
if _is_index_slice(obj):
if labels.inferred_type == 'integer':
raise
slicer = obj
indexer = obj
else:
raise

return slicer
return indexer

elif _is_list_like(obj):
if com._is_bool_indexer(obj):
Expand Down Expand Up @@ -535,8 +534,10 @@ def _tuplify(self, loc):
def _get_slice_axis(self, slice_obj, axis=0):
obj = self.obj

axis_name = obj._get_axis_name(axis)
labels = getattr(obj, axis_name)
if not _need_slice(slice_obj):
return obj

labels = obj._get_axis(axis)

int_slice = _is_index_slice(slice_obj)

Expand Down Expand Up @@ -569,23 +570,22 @@ def _get_slice_axis(self, slice_obj, axis=0):
raise

if null_slice or position_slice:
slicer = slice_obj
indexer = slice_obj
else:
try:
i, j = labels.slice_locs(start, stop)
slicer = slice(i, j, slice_obj.step)
indexer = labels.slice_indexer(start, stop, slice_obj.step)
except Exception:
if _is_index_slice(slice_obj):
if labels.inferred_type == 'integer':
raise
slicer = slice_obj
indexer = slice_obj
else:
raise

if not _need_slice(slice_obj):
return obj

return self._slice(slicer, axis=axis)
if isinstance(indexer, slice):
return self._slice(indexer, axis=axis)
else:
return self.obj.take(indexer, axis=axis)

# 32-bit floating point machine epsilon
_eps = np.finfo('f4').eps
Expand Down
49 changes: 47 additions & 2 deletions pandas/tests/test_frame.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# pylint: disable-msg=W0612,E1101
from copy import deepcopy
from datetime import datetime, timedelta
from datetime import datetime, timedelta, time
from StringIO import StringIO
import cPickle as pickle
import operator
Expand Down Expand Up @@ -4552,7 +4552,6 @@ def test_asfreq(self):
self.assert_(result is not zero_length)

def test_asfreq_datetimeindex(self):
from pandas import DatetimeIndex
df = DataFrame({'A': [1, 2, 3]},
index=[datetime(2011, 11, 01), datetime(2011, 11, 2),
datetime(2011, 11, 3)])
Expand All @@ -4562,6 +4561,52 @@ def test_asfreq_datetimeindex(self):
ts = df['A'].asfreq('B')
self.assert_(isinstance(ts.index, DatetimeIndex))

def test_at_time_between_time_datetimeindex(self):
index = pan.date_range("2012-01-01", "2012-01-05", freq='30min')
df = DataFrame(randn(len(index), 5), index=index)
akey = time(12, 0, 0)
bkey = slice(time(13, 0, 0), time(14, 0, 0))
ainds = [24, 72, 120, 168]
binds = [26, 27, 28, 74, 75, 76, 122, 123, 124, 170, 171, 172]

result = df.at_time(akey)
expected = df.ix[akey]
expected2 = df.ix[ainds]
assert_frame_equal(result, expected)
assert_frame_equal(result, expected2)
self.assert_(len(result) == 4)

result = df.between_time(bkey.start, bkey.stop)
expected = df.ix[bkey]
expected2 = df.ix[binds]
assert_frame_equal(result, expected)
assert_frame_equal(result, expected2)
self.assert_(len(result) == 12)

result = df.copy()
result.ix[akey] = 0
result = result.ix[akey]
expected = df.ix[akey].copy()
expected.ix[:] = 0
assert_frame_equal(result, expected)

result = df.copy()
result.ix[akey] = 0
result.ix[akey] = df.ix[ainds]
assert_frame_equal(result, df)

result = df.copy()
result.ix[bkey] = 0
result = result.ix[bkey]
expected = df.ix[bkey].copy()
expected.ix[:] = 0
assert_frame_equal(result, expected)

result = df.copy()
result.ix[bkey] = 0
result.ix[bkey] = df.ix[binds]
assert_frame_equal(result, df)

def test_as_matrix(self):
frame = self.frame
mat = frame.as_matrix()
Expand Down
17 changes: 17 additions & 0 deletions pandas/tseries/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,20 @@ def _get_string_slice(self, key):
loc = self._partial_date_slice(reso, parsed)
return loc

def slice_indexer(self, start=None, end=None, step=None):
"""
Index.slice_indexer, customized to handle time slicing
"""
if isinstance(start, time) and isinstance(end, time):
if step is not None and step != 1:
raise ValueError('Must have step size of 1 with time slices')
return self.indexer_between_time(start, end)

if isinstance(start, time) or isinstance(end, time):
raise KeyError('Cannot mix time and non-time slice keys')

return Index.slice_indexer(self, start, end, step)

def slice_locs(self, start=None, end=None):
"""
Index.slice_locs, customized to handle partial ISO-8601 string slicing
Expand All @@ -1172,6 +1186,9 @@ def slice_locs(self, start=None, end=None):
except KeyError:
pass

if isinstance(start, time) or isinstance(end, time):
raise KeyError('Cannot use slice_locs with time slice keys')

return Index.slice_locs(self, start, end)

def __getitem__(self, key):
Expand Down