Repository: pandas-dev/pandas

Issue:
BUG: non unique indexing via loc broken
This throws a weird error

```
df = DataFrame({'A' : [1,2,3,4], 'B' : [3, 4, 5, 6]}, index = [0,1,0,1]) 
df.loc[1:]
```

https://groups.google.com/forum/?fromgroups#!topic/pydata/zTm2No0crYs



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
@@ -1219,13 +1219,25 @@ def slice_locs(self, start=None, end=None):
         -----
         This function assumes that the data is sorted, so use at your own peril
         """
+
+        is_unique = self.is_unique
         if start is None:
             start_slice = 0
         else:
             try:
                 start_slice = self.get_loc(start)
+                
+                if not is_unique:
+
+                    # get_loc will return a boolean array for non_uniques
+                    # if we are not monotonic
+                    if isinstance(start_slice,np.ndarray):
+                        raise KeyError("cannot peform a slice operation "
+                                       "on a non-unique non-monotonic index")
+
                 if isinstance(start_slice, slice):
                     start_slice = start_slice.start
+
             except KeyError:
                 if self.is_monotonic:
                     start_slice = self.searchsorted(start, side='left')
@@ -1237,10 +1249,19 @@ def slice_locs(self, start=None, end=None):
         else:
             try:
                 end_slice = self.get_loc(end)
+
+                if not is_unique:
+
+                    # get_loc will return a boolean array for non_uniques
+                    if isinstance(end_slice,np.ndarray):
+                        raise KeyError("cannot perform a slice operation "
+                                       "on a non-unique non-monotonic index")
+
                 if isinstance(end_slice, slice):
                     end_slice = end_slice.stop
                 else:
                     end_slice += 1
+
             except KeyError:
                 if self.is_monotonic:
                     end_slice = self.searchsorted(end, side='right')
diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py
--- a/pandas/core/indexing.py
+++ b/pandas/core/indexing.py
@@ -759,6 +759,7 @@ def _getitem_axis(self, key, axis=0):
         labels = self.obj._get_axis(axis)
 
         if isinstance(key, slice):
+            self._has_valid_type(key,axis)
             return self._get_slice_axis(key, axis=axis)
         elif com._is_bool_indexer(key):
             return self._getbool_axis(key, axis=axis)


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
@@ -953,6 +953,30 @@ def test_iloc_mask(self):
                                          (key,ans,r))
         warnings.filterwarnings(action='always', category=UserWarning)
 
+    def test_non_unique_loc(self):
+        ## GH3659
+        ## non-unique indexer with loc slice
+        ## https://groups.google.com/forum/?fromgroups#!topic/pydata/zTm2No0crYs
+
+        # these are going to raise becuase the we are non monotonic
+        df = DataFrame({'A' : [1,2,3,4,5,6], 'B' : [3,4,5,6,7,8]}, index = [0,1,0,1,2,3]) 
+        self.assertRaises(KeyError, df.loc.__getitem__, tuple([slice(1,None)]))
+        self.assertRaises(KeyError, df.loc.__getitem__, tuple([slice(0,None)]))
+        self.assertRaises(KeyError, df.loc.__getitem__, tuple([slice(1,2)]))
+
+        # monotonic are ok
+        df = DataFrame({'A' : [1,2,3,4,5,6], 'B' : [3,4,5,6,7,8]}, index = [0,1,0,1,2,3]).sort(axis=0)
+        result = df.loc[1:]
+        expected = DataFrame({'A' : [2,4,5,6], 'B' : [4, 6,7,8]}, index = [1,1,2,3])
+        assert_frame_equal(result,expected)
+
+        result = df.loc[0:]
+        assert_frame_equal(result,df)
+
+        result = df.loc[1:2]
+        expected = DataFrame({'A' : [2,4,5], 'B' : [4,6,7]}, index = [1,1,2])
+        assert_frame_equal(result,expected)
+
 if __name__ == '__main__':
     import nose
     nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],