diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index ed4022d422b4d..e255f1208869e 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -363,8 +363,7 @@ Indexing - ``DataFrame.__getitem__`` now accepts dictionaries and dictionary keys as list-likes of labels, consistently with ``Series.__getitem__`` (:issue:`21294`) - Fixed ``DataFrame[np.nan]`` when columns are non-unique (:issue:`21428`) - Bug when indexing :class:`DatetimeIndex` with nanosecond resolution dates and timezones (:issue:`11679`) - -- +- Bug where indexing with a Numpy array containing negative values would mutate the indexer (:issue:`21867`) Missing ^^^^^^^ diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 80396a9149d5a..ec06099e3bbd2 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -2596,6 +2596,7 @@ def maybe_convert_indices(indices, n): mask = indices < 0 if mask.any(): + indices = indices.copy() indices[mask] += n mask = (indices >= n) | (indices < 0) diff --git a/pandas/tests/indexing/test_iloc.py b/pandas/tests/indexing/test_iloc.py index 49047e1da0996..81397002abd2b 100644 --- a/pandas/tests/indexing/test_iloc.py +++ b/pandas/tests/indexing/test_iloc.py @@ -126,6 +126,21 @@ def test_iloc_getitem_neg_int(self): typs=['labels', 'mixed', 'ts', 'floats', 'empty'], fails=IndexError) + def test_iloc_array_not_mutating_negative_indices(self): + + # GH 21867 + array_with_neg_numbers = np.array([1, 2, -1]) + array_copy = array_with_neg_numbers.copy() + df = pd.DataFrame({ + 'A': [100, 101, 102], + 'B': [103, 104, 105], + 'C': [106, 107, 108]}, + index=[1, 2, 3]) + df.iloc[array_with_neg_numbers] + tm.assert_numpy_array_equal(array_with_neg_numbers, array_copy) + df.iloc[:, array_with_neg_numbers] + tm.assert_numpy_array_equal(array_with_neg_numbers, array_copy) + def test_iloc_getitem_list_int(self): # list of ints