diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index b962add29db33..c49767e80f535 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -546,6 +546,7 @@ Datetimelike - Bug in constructing a :class:`Series` from datetime-like strings with mixed timezones incorrectly partially-inferring datetime values (:issue:`40111`) - Bug in addition with a :class:`Tick` object and a ``np.timedelta64`` object incorrectly raising instead of returning :class:`Timedelta` (:issue:`44474`) - Bug in adding a ``np.timedelta64`` object to a :class:`BusinessDay` or :class:`CustomBusinessDay` object incorrectly raising (:issue:`44532`) +- Bug in :meth:`Index.insert` for inserting ``np.datetime64``, ``np.timedelta64`` or ``tuple`` into :class:`Index` with ``dtype='object'`` with negative loc addine ``None`` and replacing existing value (:issue:`44509`) - Timedelta diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 01bf5ec0633b5..96a76aa930f86 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -1496,7 +1496,7 @@ def _putmask(self, mask: npt.NDArray[np.bool_], value) -> None: def insert(self: IntervalArrayT, loc: int, item: Interval) -> IntervalArrayT: """ Return a new IntervalArray inserting new item at location. Follows - Python list.append semantics for negative values. Only Interval + Python numpy.insert semantics for negative values. Only Interval objects and NA can be inserted into an IntervalIndex Parameters diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index a49c303e735ab..220b43f323a5f 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -6433,7 +6433,7 @@ def insert(self, loc: int, item) -> Index: """ Make new Index inserting new item at location. - Follows Python list.append semantics for negative values. + Follows Python numpy.insert semantics for negative values. Parameters ---------- @@ -6476,6 +6476,7 @@ def insert(self, loc: int, item) -> Index: else: new_values = np.insert(arr, loc, None) + loc = loc if loc >= 0 else loc - 1 new_values[loc] = item # Use self._constructor instead of Index to retain NumericIndex GH#43921 diff --git a/pandas/tests/indexes/base_class/test_reshape.py b/pandas/tests/indexes/base_class/test_reshape.py index acb6936f70d0f..547d62669943c 100644 --- a/pandas/tests/indexes/base_class/test_reshape.py +++ b/pandas/tests/indexes/base_class/test_reshape.py @@ -1,6 +1,7 @@ """ Tests for ndarray-like method on the base Index class """ +import numpy as np import pytest from pandas import Index @@ -42,6 +43,18 @@ def test_insert_missing(self, nulls_fixture): result = Index(list("abc")).insert(1, nulls_fixture) tm.assert_index_equal(result, expected) + @pytest.mark.parametrize( + "val", [(1, 2), np.datetime64("2019-12-31"), np.timedelta64(1, "D")] + ) + @pytest.mark.parametrize("loc", [-1, 2]) + def test_insert_datetime_into_object(self, loc, val): + # GH#44509 + idx = Index(["1", "2", "3"]) + result = idx.insert(loc, val) + expected = Index(["1", "2", val, "3"]) + tm.assert_index_equal(result, expected) + assert type(expected[2]) is type(val) + @pytest.mark.parametrize( "pos,expected", [