diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index da953fe46ef1d..2ff9b3973a526 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -6329,10 +6329,11 @@ def insert(self, loc: int, item) -> Index: arr = np.asarray(self) - # Use Index constructor to ensure we get tuples cast correctly. - item = Index([item], dtype=self.dtype)._values + # Use constructor to ensure we get tuples cast correctly. + # Use self._constructor instead of Index to retain NumericIndex GH#43921 + item = self._constructor([item], dtype=self.dtype)._values idx = np.concatenate((arr[:loc], item, arr[loc:])) - return Index._with_infer(idx, name=self.name) + return self._constructor._with_infer(idx, name=self.name) def drop(self, labels, errors: str_t = "raise") -> Index: """ diff --git a/pandas/tests/indexes/common.py b/pandas/tests/indexes/common.py index 8357595fdaa40..7e43664c6b3de 100644 --- a/pandas/tests/indexes/common.py +++ b/pandas/tests/indexes/common.py @@ -793,6 +793,20 @@ def test_format(self, simple_index): def test_numeric_compat(self): pass # override Base method + def test_insert_non_na(self, simple_index): + # GH#43921 inserting an element that we know we can hold should + # not change dtype or type (except for RangeIndex) + index = simple_index + + result = index.insert(0, index[0]) + + cls = type(index) + if cls is RangeIndex: + cls = Int64Index + + expected = cls([index[0]] + list(index), dtype=index.dtype) + tm.assert_index_equal(result, expected) + def test_insert_na(self, nulls_fixture, simple_index): # GH 18295 (test missing) index = simple_index @@ -800,6 +814,11 @@ def test_insert_na(self, nulls_fixture, simple_index): if na_val is pd.NaT: expected = Index([index[0], pd.NaT] + list(index[1:]), dtype=object) + elif type(index) is NumericIndex and index.dtype.kind == "f": + # GH#43921 + expected = NumericIndex( + [index[0], np.nan] + list(index[1:]), dtype=index.dtype + ) else: expected = Float64Index([index[0], np.nan] + list(index[1:]))