Repository: pandas-dev/pandas

Issue:
BUG: Indexing with duplicate columns
Currently failing test case:

``` python
df = DataFrame([[1,2,'foo','bar']], columns=['a','a','a','a'])
s = Series([1, 2, 'foo', 'bar'], index=['a', 'a', 'a', 'a'], name=0)
assert_series_equal(df.irow(0), s)
```

Here's what's going on right now.

``` python
In [3]: from pandas import *
In [4]: df = DataFrame([[1,2,'foo','bar']], columns=['a','a','a','a'])
In [5]: df
Out[5]:
   a  a    a    a
0  1  2  foo  bar

In [6]: df.irow(0)
Out[6]:
a    bar
a    bar
a    bar
a    bar
Name: 0, dtype: object

In [7]: df.icol(0)
Out[7]:
0    1
Name: a, dtype: int64

In [8]: df.columns
Out[8]: Index([u'a', u'a', u'a', u'a'], dtype=object)
```



Discussion:
Also same with iloc:

```
In [9]: df.iloc[0, :]
Out[9]:
a    bar
a    bar
a    bar
a    bar
Name: 0, dtype: object
```

cc @jreback 

yep...this hits an older path that was never fixed for the _ref_locs.....


Resolving patch:
diff --git a/pandas/core/internals.py b/pandas/core/internals.py
--- a/pandas/core/internals.py
+++ b/pandas/core/internals.py
@@ -72,9 +72,6 @@ def __init__(self, values, items, ref_items, ndim=None, fastpath=False, placemen
             self.items = _ensure_index(items)
             self.ref_items = _ensure_index(ref_items)
 
-    def _gi(self, arg):
-        return self.values[arg]
-
     @property
     def _consolidate_key(self):
         return (self._can_consolidate, self.dtype.name)
@@ -1165,9 +1162,6 @@ def __init__(self, values, items, ref_items, fastpath=False, placement=None, **k
         super(DatetimeBlock, self).__init__(values, items, ref_items,
                                             fastpath=True, placement=placement, **kwargs)
 
-    def _gi(self, arg):
-        return lib.Timestamp(self.values[arg])
-
     def _can_hold_element(self, element):
         if is_list_like(element):
             element = np.array(element)
@@ -1200,7 +1194,7 @@ def _try_coerce_result(self, result):
             if result.dtype == 'i8':
                 result = tslib.array_to_datetime(
                     result.astype(object).ravel()).reshape(result.shape)
-        elif isinstance(result, np.integer):
+        elif isinstance(result, (np.integer, np.datetime64)):
             result = lib.Timestamp(result)
         return result
 
@@ -1267,10 +1261,9 @@ def set(self, item, value):
         self.values[loc] = value
 
     def get_values(self, dtype=None):
+        # return object dtype as Timestamps
         if dtype == object:
-            flat_i8 = self.values.ravel().view(np.int64)
-            res = tslib.ints_to_pydatetime(flat_i8)
-            return res.reshape(self.values.shape)
+            return lib.map_infer(self.values.ravel(), lib.Timestamp).reshape(self.values.shape)
         return self.values
 
 
@@ -2272,7 +2265,8 @@ def xs(self, key, axis=1, copy=True):
 
     def fast_2d_xs(self, loc, copy=False):
         """
-
+        get a cross sectional for a given location in the
+        items ; handle dups
         """
         if len(self.blocks) == 1:
             result = self.blocks[0].values[:, loc]
@@ -2284,15 +2278,20 @@ def fast_2d_xs(self, loc, copy=False):
             raise Exception('cannot get view of mixed-type or '
                             'non-consolidated DataFrame')
 
-        dtype = _interleaved_dtype(self.blocks)
-
         items = self.items
+
+        # non-unique (GH4726)
+        if not items.is_unique:
+            return self._interleave(items).ravel()
+
+        # unique
+        dtype = _interleaved_dtype(self.blocks)
         n = len(items)
         result = np.empty(n, dtype=dtype)
         for blk in self.blocks:
             for j, item in enumerate(blk.items):
                 i = items.get_loc(item)
-                result[i] = blk._gi((j, loc))
+                result[i] = blk._try_coerce_result(blk.iget((j, loc)))
 
         return result
 


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
@@ -1215,6 +1215,20 @@ def test_astype_assignment_with_iloc(self):
         result = df.get_dtype_counts().sort_index()
         expected = Series({ 'int64' : 4, 'float64' : 1, 'object' : 2 }).sort_index()
 
+    def test_dups_loc(self):
+
+        # GH4726
+        # dup indexing with iloc/loc
+        df = DataFrame([[1,2,'foo','bar',Timestamp('20130101')]],
+                       columns=['a','a','a','a','a'],index=[1])
+        expected = Series([1,2,'foo','bar',Timestamp('20130101')],index=['a','a','a','a','a'])
+
+        result = df.iloc[0]
+        assert_series_equal(result,expected)
+
+        result = df.loc[1]
+        assert_series_equal(result,expected)
+
 if __name__ == '__main__':
     import nose
     nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],