Skip to content

Commit 353b6f9

Browse files
committed
BUG: do not raise UnsortedIndexError if sorting is not required
closes pandas-dev#16734
1 parent 45add48 commit 353b6f9

File tree

4 files changed

+19
-6
lines changed

4 files changed

+19
-6
lines changed

doc/source/whatsnew/v0.21.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ Indexing
9898
^^^^^^^^
9999

100100
- 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`).
101+
- 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`).
101102

102103

103104
I/O

pandas/core/indexes/multi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2265,7 +2265,7 @@ def get_locs(self, tup):
22652265

22662266
# must be lexsorted to at least as many levels
22672267
last_slice = max(self._true_slices_indices(tup))
2268-
if last_slice > self.lexsort_depth:
2268+
if last_slice >= self.lexsort_depth:
22692269
raise UnsortedIndexError('MultiIndex Slicing requires the index '
22702270
'to be lexsorted: slicing on level ({0}), '
22712271
'lexsort depth ({1})'

pandas/tests/indexes/test_multi.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -2826,8 +2826,11 @@ def test_unsortedindex(self):
28262826
df = pd.DataFrame([[i, 10 * i] for i in lrange(6)], index=mi,
28272827
columns=['one', 'two'])
28282828

2829+
# GH 16734
2830+
tm.assert_series_equal(df.loc(axis=0)['z', 'a'], df.iloc[0])
2831+
28292832
with pytest.raises(UnsortedIndexError):
2830-
df.loc(axis=0)['z', :]
2833+
df.loc(axis=0)['z', slice('a')]
28312834
df.sort_index(inplace=True)
28322835
assert len(df.loc(axis=0)['z', :]) == 2
28332836

pandas/tests/indexing/test_multiindex.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -817,9 +817,13 @@ def f():
817817
assert df.index.lexsort_depth == 0
818818
with tm.assert_raises_regex(
819819
UnsortedIndexError,
820-
'MultiIndex Slicing requires the index to be fully '
821-
r'lexsorted tuple len \(2\), lexsort depth \(0\)'):
822-
df.loc[(slice(None), df.loc[:, ('a', 'bar')] > 5), :]
820+
'MultiIndex Slicing requires the index to be '
821+
r'lexsorted: slicing on level \(1\), lexsort depth \(0\)'):
822+
df.loc[(slice(None), slice('bar')), :]
823+
824+
# GH 16734
825+
result = df.loc[(slice(None), df.loc[:, ('a', 'bar')] > 5), :]
826+
tm.assert_frame_equal(result, df.iloc[[1, 3], :])
823827

824828
def test_multiindex_slicers_non_unique(self):
825829

@@ -1001,9 +1005,14 @@ def test_per_axis_per_level_doc_examples(self):
10011005

10021006
# not sorted
10031007
def f():
1004-
df.loc['A1', (slice(None), 'foo')]
1008+
df.loc['A1', ('a', slice('foo'))]
10051009

10061010
pytest.raises(UnsortedIndexError, f)
1011+
1012+
# GH 16734: not sorted, but no real slicing
1013+
tm.assert_frame_equal(df.loc['A1', (slice(None), 'foo')],
1014+
df.loc['A1'].iloc[:, [0,2]])
1015+
10071016
df = df.sort_index(axis=1)
10081017

10091018
# slicing

0 commit comments

Comments
 (0)