Skip to content

Commit

Permalink
BUG: do not raise UnsortedIndexError if sorting is not required
Browse files Browse the repository at this point in the history
  • Loading branch information
toobaz committed Jun 20, 2017
1 parent 45add48 commit da5d8ec
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 10 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.21.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Indexing
^^^^^^^^

- When called with a null slice (e.g. ``df.iloc[:]``), the``iloc`` and ``loc`` indexers return a shallow copy of the original object. Previously they returned the original object. (:issue:`13873`).
- When called on an unsorted ``MultiIndex``, the ``loc`` indexer now will raise ``UnsortedIndexError`` only if proper slicing is used on non-sorted levels (:issue:`16734`).


I/O
Expand Down
10 changes: 5 additions & 5 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,8 +1039,8 @@ def _true_slices_indices(self, tup):
"""
Return indices of (non-trivial) slices in "tup"
"""
slices = lambda k : (isinstance(k, slice)
and (k.start is not None or k.stop is not None))
slices = lambda k: (isinstance(k, slice) and
(k.start is not None or k.stop is not None))
return [(i if slices(k) else -1) for (i, k) in enumerate(tup)]

@cache_readonly
Expand Down Expand Up @@ -2265,10 +2265,10 @@ def get_locs(self, tup):

# must be lexsorted to at least as many levels
last_slice = max(self._true_slices_indices(tup))
if last_slice > self.lexsort_depth:
if last_slice >= self.lexsort_depth:
raise UnsortedIndexError('MultiIndex Slicing requires the index '
'to be lexsorted: slicing on level ({0}), '
'lexsort depth ({1})'
'to be lexsorted: slicing on level '
'({0}), lexsort depth ({1})'
.format(last_slice, self.lexsort_depth))
# indexer
# this is the list of all values that we want to select
Expand Down
5 changes: 4 additions & 1 deletion pandas/tests/indexes/test_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2826,8 +2826,11 @@ def test_unsortedindex(self):
df = pd.DataFrame([[i, 10 * i] for i in lrange(6)], index=mi,
columns=['one', 'two'])

# GH 16734
tm.assert_series_equal(df.loc(axis=0)['z', 'a'], df.iloc[0])

with pytest.raises(UnsortedIndexError):
df.loc(axis=0)['z', :]
df.loc(axis=0)['z', slice('a')]
df.sort_index(inplace=True)
assert len(df.loc(axis=0)['z', :]) == 2

Expand Down
17 changes: 13 additions & 4 deletions pandas/tests/indexing/test_multiindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,9 +817,13 @@ def f():
assert df.index.lexsort_depth == 0
with tm.assert_raises_regex(
UnsortedIndexError,
'MultiIndex Slicing requires the index to be fully '
r'lexsorted tuple len \(2\), lexsort depth \(0\)'):
df.loc[(slice(None), df.loc[:, ('a', 'bar')] > 5), :]
'MultiIndex Slicing requires the index to be '
r'lexsorted: slicing on level \(1\), lexsort depth \(0\)'):
df.loc[(slice(None), slice('bar')), :]

# GH 16734
result = df.loc[(slice(None), df.loc[:, ('a', 'bar')] > 5), :]
tm.assert_frame_equal(result, df.iloc[[1, 3], :])

def test_multiindex_slicers_non_unique(self):

Expand Down Expand Up @@ -1001,9 +1005,14 @@ def test_per_axis_per_level_doc_examples(self):

# not sorted
def f():
df.loc['A1', (slice(None), 'foo')]
df.loc['A1', ('a', slice('foo'))]

pytest.raises(UnsortedIndexError, f)

# GH 16734: not sorted, but no real slicing
tm.assert_frame_equal(df.loc['A1', (slice(None), 'foo')],
df.loc['A1'].iloc[:, [0, 2]])

df = df.sort_index(axis=1)

# slicing
Expand Down

0 comments on commit da5d8ec

Please sign in to comment.