From 785f407b7ad5f2782ebbe0d52597e396a030efb1 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Sun, 15 Jun 2014 15:51:53 -0700 Subject: [PATCH] ENH: Cast ndarray-like datetime64 arrays to Index properly It turns out that the ndarray-like arrays of dtype datetime64 were not being properly cast to an Index, because -- due to a bug with np.datetime64 -- calling np.asarray(x, dtype=object) if x is an ndarray of type datetime64 results in an *integer* array. This PR adds tests and a work around to pd.Index.__new__. Related #5460 --- pandas/core/index.py | 3 +++ pandas/tests/test_index.py | 15 ++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pandas/core/index.py b/pandas/core/index.py index 2252ba666ca59..6cbffd5b4dbba 100644 --- a/pandas/core/index.py +++ b/pandas/core/index.py @@ -148,6 +148,9 @@ def __new__(cls, data, dtype=None, copy=False, name=None, fastpath=False, if copy: subarr = subarr.copy() + elif hasattr(data, '__array__'): + return Index(np.asarray(data), dtype=dtype, copy=copy, name=name, + **kwargs) elif np.isscalar(data): cls._scalar_data_error(data) else: diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index f2372f98b330b..203d3f26d0812 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -177,12 +177,17 @@ def test_constructor_ndarray_like(self): # it should be possible to convert any object that satisfies the numpy # ndarray interface directly into an Index class ArrayLike(object): + def __init__(self, array): + self.array = array def __array__(self, dtype=None): - return np.arange(5) + return self.array - expected = pd.Index(np.arange(5)) - result = pd.Index(ArrayLike()) - self.assertTrue(result.equals(expected)) + for array in [np.arange(5), + np.array(['a', 'b', 'c']), + pd.date_range('2000-01-01', periods=3).values]: + expected = pd.Index(array) + result = pd.Index(ArrayLike(array)) + self.assertTrue(result.equals(expected)) def test_index_ctor_infer_periodindex(self): from pandas import period_range, PeriodIndex @@ -447,7 +452,7 @@ def test_intersection(self): assertRaisesRegexp(TypeError, "iterable", first.intersection, 0.5) idx1 = Index([1, 2, 3, 4, 5], name='idx') - # if target has the same name, it is preserved + # if target has the same name, it is preserved idx2 = Index([3, 4, 5, 6, 7], name='idx') expected2 = Index([3, 4, 5], name='idx') result2 = idx1.intersection(idx2)