Repository: pandas-dev/pandas

Issue:
API: non-unique indexing on Series
The following currently are exceptions in master(the corresponding operations on DataFrames work though)

```
In [4]: s = Series([1,2,3,4],['foo','bar','foo','bah'])

In [5]: s.ix[['foo','bar','bah','bam']]
NotImplementedError: cannot handle non-unique indexing for non-DataFrame (yet)

In [6]: s[['foo','bar','bah','bam']]
AssertionError: Index length did not match values
```



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
@@ -928,7 +928,7 @@ def reindex(self, target, method=None, level=None, limit=None,
                     if method is not None or limit is not None:
                         raise ValueError("cannot reindex a non-unique index "
                                          "with a method or limit")
-                    indexer, _ = self.get_indexer_non_unique(target)
+                    indexer, missing = self.get_indexer_non_unique(target)
 
         return target, indexer
 
diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py
--- a/pandas/core/indexing.py
+++ b/pandas/core/indexing.py
@@ -481,12 +481,12 @@ def _reindex(keys, level=None):
                     new_indexer = (Index(cur_indexer) + Index(missing_indexer)).values
                     new_indexer[missing_indexer] = -1
 
-                    # need to reindex with an indexer on a specific axis
-                    from pandas.core.frame import DataFrame
-                    if not (type(self.obj) == DataFrame):
-                        raise NotImplementedError("cannot handle non-unique indexing for non-DataFrame (yet)")
+                    # reindex with the specified axis
+                    ndim = self.obj.ndim
+                    if axis+1 > ndim:
+                        raise AssertionError("invalid indexing error with non-unique index")
 
-                    args = [None] * 4
+                    args = [None] * (2*ndim)
                     args[2*axis] = new_labels
                     args[2*axis+1] = new_indexer
 
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -681,6 +681,10 @@ def _get_with(self, key):
                 return self._get_values(key)
             else:
                 try:
+                    # handle the dup indexing case (GH 4246)
+                    if isinstance(key, (list,tuple)):
+                        return self.ix[key]
+
                     return self.reindex(key)
                 except Exception:
                     # [slice(0, 5, None)] will break if you convert to ndarray,
@@ -2637,8 +2641,13 @@ def reindex(self, index=None, method=None, level=None, fill_value=pa.NA,
         new_index, indexer = self.index.reindex(index, method=method,
                                                 level=level, limit=limit,
                                                 takeable=takeable)
+
+        # GH4246 (dispatch to a common method with frame to handle possibly duplicate index)
+        return self._reindex_with_indexers(new_index, indexer, copy=copy, fill_value=fill_value)
+
+    def _reindex_with_indexers(self, index, indexer, copy, fill_value):
         new_values = com.take_1d(self.values, indexer, fill_value=fill_value)
-        return Series(new_values, index=new_index, name=self.name)
+        return Series(new_values, index=index, name=self.name)
 
     def reindex_axis(self, labels, axis=0, **kwargs):
         """ for compatibility with higher dims """


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -788,6 +788,15 @@ def test_getitem_unordered_dup(self):
         self.assert_(np.isscalar(obj['c']))
         self.assert_(obj['c'] == 0)
 
+    def test_getitem_dups_with_missing(self):
+
+        # breaks reindex, so need to use .ix internally
+        # GH 4246
+        s = Series([1,2,3,4],['foo','bar','foo','bah'])
+        expected = s.ix[['foo','bar','bah','bam']]
+        result = s[['foo','bar','bah','bam']]
+        assert_series_equal(result,expected)
+
     def test_setitem_ambiguous_keyerror(self):
         s = Series(range(10), index=range(0, 20, 2))
         self.assertRaises(KeyError, s.__setitem__, 1, 5)
@@ -1141,7 +1150,7 @@ def test_where(self):
         s = Series(np.arange(10))
         mask = s > 5
         self.assertRaises(ValueError, s.__setitem__, mask, ([0]*5,))
-        
+
     def test_where_broadcast(self):
         # Test a variety of differently sized series
         for size in range(2, 6):