diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index c91ced1014dd1..162f9dea06482 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -343,6 +343,7 @@ Numeric - Bug in :class:`DataFrame` logical operations (`&`, `|`, `^`) not matching :class:`Series` behavior by filling NA values (:issue:`28741`) - Bug in :meth:`DataFrame.interpolate` where specifying axis by name references variable before it is assigned (:issue:`29142`) - Improved error message when using `frac` > 1 and `replace` = False (:issue:`27451`) +- Bug in :class:`UInt64Index` precision loss while constructing from a list with values in the ``np.uint64`` range (:issue:`29526`) - Conversion diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index c554c501ae7ce..2321e077df285 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4027,30 +4027,6 @@ def _string_data_error(cls, data): "to explicitly cast to a numeric type" ) - @classmethod - def _coerce_to_ndarray(cls, data): - """ - Coerces data to ndarray. - - Converts other iterables to list first and then to array. - Does not touch ndarrays. - - Raises - ------ - TypeError - When the data passed in is a scalar. - """ - - if not isinstance(data, (np.ndarray, Index)): - if data is None or is_scalar(data): - raise cls._scalar_data_error(data) - - # other iterable of some kind - if not isinstance(data, (ABCSeries, list, tuple)): - data = list(data) - data = np.asarray(data) - return data - def _coerce_scalar_to_index(self, item): """ We need to coerce a scalar to a compat for our index type. diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index ee96e4cd699bb..074cce085fb3c 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -22,6 +22,7 @@ ABCFloat64Index, ABCInt64Index, ABCRangeIndex, + ABCSeries, ABCUInt64Index, ) from pandas.core.dtypes.missing import isna @@ -55,8 +56,16 @@ def __new__(cls, data=None, dtype=None, copy=False, name=None, fastpath=None): if fastpath: return cls._simple_new(data, name=name) - # is_scalar, generators handled in coerce_to_ndarray - data = cls._coerce_to_ndarray(data) + # Coerce to ndarray if not already ndarray or Index + if not isinstance(data, (np.ndarray, Index)): + if is_scalar(data): + raise cls._scalar_data_error(data) + + # other iterable of some kind + if not isinstance(data, (ABCSeries, list, tuple)): + data = list(data) + + data = np.asarray(data, dtype=dtype) if issubclass(data.dtype.type, str): cls._string_data_error(data) diff --git a/pandas/tests/indexes/test_numeric.py b/pandas/tests/indexes/test_numeric.py index deb63cc9ef854..e0f7b1d1ade3d 100644 --- a/pandas/tests/indexes/test_numeric.py +++ b/pandas/tests/indexes/test_numeric.py @@ -944,6 +944,11 @@ def test_constructor(self): res = Index(np.array([-1, 2 ** 63], dtype=object)) tm.assert_index_equal(res, idx) + # https://github.com/pandas-dev/pandas/issues/29526 + idx = UInt64Index([1, 2 ** 63 + 1], dtype=np.uint64) + res = Index([1, 2 ** 63 + 1], dtype=np.uint64) + tm.assert_index_equal(res, idx) + def test_get_indexer(self, index_large): target = UInt64Index(np.arange(10).astype("uint64") * 5 + 2 ** 63) indexer = index_large.get_indexer(target)