Repository: pandas-dev/pandas

Issue:
BUG: multiindex slicers requires a unique index
This is actually not required, and so should work I think
(requires lexsorting only)

```
In [70]: df = DataFrame(dict(A = ['foo','foo','foo','foo'], B = ['a','a','a','a'], C = [1,2,1,3], D = [1,2,3,4])).set_index(['A','B','C']).sortlevel()

In [71]: df
Out[71]: 
         D
A   B C   
foo a 1  1
      1  3
      2  2
      3  4

[4 rows x 1 columns]

In [72]: df.xs(1,level=2)
Out[72]: 
       D
A   B   
foo a  1
    a  3

[2 rows x 1 columns]

In [73]: df.loc[(slice(None),slice(None),1),:]
ValueError: MultiIndex Slicing requires a unique index
```



Discussion:

Resolving patch:
diff --git a/pandas/core/index.py b/pandas/core/index.py
--- a/pandas/core/index.py
+++ b/pandas/core/index.py
@@ -2595,7 +2595,7 @@ def get_level_values(self, level):
         unique = self.levels[num]  # .values
         labels = self.labels[num]
         filled = com.take_1d(unique.values, labels, fill_value=unique._na_value)
-        values = unique._simple_new(filled, self.names[num], 
+        values = unique._simple_new(filled, self.names[num],
                                     freq=getattr(unique, 'freq', None),
                                     tz=getattr(unique, 'tz', None))
         return values
@@ -3556,8 +3556,6 @@ def get_locs(self, tup):
         if not self.is_lexsorted_for_tuple(tup):
             raise KeyError('MultiIndex Slicing requires the index to be fully lexsorted'
                            ' tuple len ({0}), lexsort depth ({1})'.format(len(tup), self.lexsort_depth))
-        if not self.is_unique:
-            raise ValueError('MultiIndex Slicing requires a unique index')
 
         def _convert_indexer(r):
             if isinstance(r, slice):


Test patch:
diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py
--- a/pandas/tests/test_indexing.py
+++ b/pandas/tests/test_indexing.py
@@ -1356,6 +1356,47 @@ def f():
             df.loc[(slice(None),[1])]
         self.assertRaises(KeyError, f)
 
+        # not lexsorted
+        self.assertEquals(df.index.lexsort_depth,2)
+        df = df.sortlevel(level=1,axis=0)
+        self.assertEquals(df.index.lexsort_depth,0)
+        with tm.assertRaisesRegexp(KeyError, 'MultiIndex Slicing requires the index to be fully lexsorted tuple len \(2\), lexsort depth \(0\)'):
+            df.loc[(slice(None),df.loc[:,('a','bar')]>5),:]
+
+    def test_multiindex_slicers_non_unique(self):
+
+        # GH 7106
+        # non-unique mi index support
+        df = DataFrame(dict(A = ['foo','foo','foo','foo'],
+                            B = ['a','a','a','a'],
+                            C = [1,2,1,3],
+                            D = [1,2,3,4])).set_index(['A','B','C']).sortlevel()
+        self.assertFalse(df.index.is_unique)
+        expected = DataFrame(dict(A = ['foo','foo'],
+                                  B = ['a','a'],
+                                  C = [1,1],
+                                  D = [1,3])).set_index(['A','B','C']).sortlevel()
+        result = df.loc[(slice(None),slice(None),1),:]
+        assert_frame_equal(result, expected)
+
+        # this is equivalent of an xs expression
+        result = df.xs(1,level=2,drop_level=False)
+        assert_frame_equal(result, expected)
+
+        df = DataFrame(dict(A = ['foo','foo','foo','foo'],
+                            B = ['a','a','a','a'],
+                            C = [1,2,1,2],
+                            D = [1,2,3,4])).set_index(['A','B','C']).sortlevel()
+        self.assertFalse(df.index.is_unique)
+        expected = DataFrame(dict(A = ['foo','foo'],
+                                  B = ['a','a'],
+                                  C = [1,1],
+                                  D = [1,3])).set_index(['A','B','C']).sortlevel()
+        result = df.loc[(slice(None),slice(None),1),:]
+        self.assertFalse(result.index.is_unique)
+        assert_frame_equal(result, expected)
+
+
     def test_per_axis_per_level_doc_examples(self):
 
         # test index maker