diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index c24c94a786068..0bc568fb122ed 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4962,14 +4962,6 @@ def _raise_scalar_data_error(cls, data): f"kind, {repr(data)} was passed" ) - @final - @classmethod - def _string_data_error(cls, data): - raise TypeError( - "String dtype not supported, you may need " - "to explicitly cast to a numeric type" - ) - def _validate_fill_value(self, value): """ Check if the value can be inserted into our array without casting, diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index 816a1752c5bf0..328e3d2f401e6 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -32,6 +32,7 @@ ) from pandas.core.dtypes.generic import ABCSeries +from pandas.core.construction import sanitize_array from pandas.core.indexes.base import ( Index, maybe_extract_name, @@ -144,15 +145,17 @@ def _ensure_array(cls, data, dtype, copy: bool): data = list(data) orig = data - data = np.asarray(data, dtype=dtype) + if isinstance(data, (list, tuple)): + if len(data): + data = sanitize_array(data, index=None) + else: + data = np.array([], dtype=np.int64) + if dtype is None and data.dtype.kind == "f": if cls is UInt64Index and (data >= 0).all(): # https://github.com/numpy/numpy/issues/19146 data = np.asarray(orig, dtype=np.uint64) - if issubclass(data.dtype.type, str): - cls._string_data_error(data) - dtype = cls._ensure_dtype(dtype) if copy or not is_dtype_equal(data.dtype, dtype): @@ -198,7 +201,8 @@ def _ensure_dtype(cls, dtype: Dtype | None) -> np.dtype | None: return cls._default_dtype dtype = pandas_dtype(dtype) - assert isinstance(dtype, np.dtype) + if not isinstance(dtype, np.dtype): + raise TypeError(f"{dtype} not a numpy type") if cls._is_backward_compat_public_numeric_index: # dtype for NumericIndex diff --git a/pandas/tests/indexes/numeric/test_numeric.py b/pandas/tests/indexes/numeric/test_numeric.py index 8901ef7cb3e33..c06fce4811f12 100644 --- a/pandas/tests/indexes/numeric/test_numeric.py +++ b/pandas/tests/indexes/numeric/test_numeric.py @@ -64,6 +64,10 @@ def check_coerce(self, a, b, is_float_index=True): else: self.check_is_index(b) + def test_constructor_from_list_no_dtype(self): + index = self._index_cls([1.5, 2.5, 3.5]) + assert index.dtype == np.float64 + def test_constructor(self, dtype): index_cls = self._index_cls @@ -115,17 +119,10 @@ def test_constructor_invalid(self): with pytest.raises(TypeError, match=msg): index_cls(0.0) - # 2021-02-1 we get ValueError in numpy 1.20, but not on all builds - msg = "|".join( - [ - "String dtype not supported, you may need to explicitly cast ", - "could not convert string to float: 'a'", - ] - ) - with pytest.raises((TypeError, ValueError), match=msg): + msg = f"data is not compatible with {index_cls.__name__}" + with pytest.raises(ValueError, match=msg): index_cls(["a", "b", 0.0]) - msg = f"data is not compatible with {index_cls.__name__}" with pytest.raises(ValueError, match=msg): index_cls([Timestamp("20130101")]) @@ -327,18 +324,16 @@ def test_identical(self, simple_index, dtype): assert not index.astype(dtype=object).identical(index.astype(dtype=dtype)) def test_cant_or_shouldnt_cast(self): - msg = ( - "String dtype not supported, " - "you may need to explicitly cast to a numeric type" - ) + msg = f"data is not compatible with {self._index_cls.__name__}" + # can't data = ["foo", "bar", "baz"] - with pytest.raises(TypeError, match=msg): + with pytest.raises(ValueError, match=msg): self._index_cls(data) # shouldn't data = ["0", "1", "2"] - with pytest.raises(TypeError, match=msg): + with pytest.raises(ValueError, match=msg): self._index_cls(data) def test_view_index(self, simple_index): @@ -372,6 +367,10 @@ def simple_index(self, dtype): def index(self, request, dtype): return self._index_cls(request.param, dtype=dtype) + def test_constructor_from_list_no_dtype(self): + index = self._index_cls([1, 2, 3]) + assert index.dtype == np.int64 + def test_constructor(self, dtype): index_cls = self._index_cls