Skip to content

Commit 124b671

Browse files
authored
DEPR: Index.insert dtype-inference (#55257)
1 parent e3073b5 commit 124b671

File tree

5 files changed

+49
-10
lines changed

5 files changed

+49
-10
lines changed

doc/source/whatsnew/v2.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ Other Deprecations
454454
- Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_string` except ``buf``. (:issue:`54229`)
455455
- Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_xml` except ``path_or_buffer``. (:issue:`54229`)
456456
- Deprecated allowing passing :class:`BlockManager` objects to :class:`DataFrame` or :class:`SingleBlockManager` objects to :class:`Series` (:issue:`52419`)
457+
- Deprecated behavior of :meth:`Index.insert` with an object-dtype index silently performing type inference on the result, explicitly call ``result.infer_objects(copy=False)`` for the old behavior instead (:issue:`51363`)
457458
- Deprecated downcasting behavior in :meth:`Series.where`, :meth:`DataFrame.where`, :meth:`Series.mask`, :meth:`DataFrame.mask`, :meth:`Series.clip`, :meth:`DataFrame.clip`; in a future version these will not infer object-dtype columns to non-object dtype, or all-round floats to integer dtype. Call ``result.infer_objects(copy=False)`` on the result for object inference, or explicitly cast floats to ints. To opt in to the future version, use ``pd.set_option("future.no_silent_downcasting", True)`` (:issue:`53656`)
458459
- Deprecated including the groups in computations when using :meth:`.DataFrameGroupBy.apply` and :meth:`.DataFrameGroupBy.resample`; pass ``include_groups=False`` to exclude the groups (:issue:`7155`)
459460
- Deprecated indexing an :class:`Index` with a boolean indexer of length zero (:issue:`55820`)

pandas/core/indexes/base.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -6939,14 +6939,24 @@ def insert(self, loc: int, item) -> Index:
69396939
loc = loc if loc >= 0 else loc - 1
69406940
new_values[loc] = item
69416941

6942-
idx = Index._with_infer(new_values, name=self.name)
6942+
out = Index._with_infer(new_values, name=self.name)
69436943
if (
69446944
using_pyarrow_string_dtype()
6945-
and is_string_dtype(idx.dtype)
6945+
and is_string_dtype(out.dtype)
69466946
and new_values.dtype == object
69476947
):
6948-
idx = idx.astype(new_values.dtype)
6949-
return idx
6948+
out = out.astype(new_values.dtype)
6949+
if self.dtype == object and out.dtype != object:
6950+
# GH#51363
6951+
warnings.warn(
6952+
"The behavior of Index.insert with object-dtype is deprecated, "
6953+
"in a future version this will return an object-dtype Index "
6954+
"instead of inferring a non-object dtype. To retain the old "
6955+
"behavior, do `idx.insert(loc, item).infer_objects(copy=False)`",
6956+
FutureWarning,
6957+
stacklevel=find_stack_level(),
6958+
)
6959+
return out
69506960

69516961
def drop(
69526962
self,

pandas/core/indexing.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,15 @@ def _setitem_with_indexer(self, indexer, value, name: str = "iloc"):
18931893
# just replacing the block manager here
18941894
# so the object is the same
18951895
index = self.obj._get_axis(i)
1896-
labels = index.insert(len(index), key)
1896+
with warnings.catch_warnings():
1897+
# TODO: re-issue this with setitem-specific message?
1898+
warnings.filterwarnings(
1899+
"ignore",
1900+
"The behavior of Index.insert with object-dtype "
1901+
"is deprecated",
1902+
category=FutureWarning,
1903+
)
1904+
labels = index.insert(len(index), key)
18971905

18981906
# We are expanding the Series/DataFrame values to match
18991907
# the length of thenew index `labels`. GH#40096 ensure
@@ -2186,7 +2194,14 @@ def _setitem_with_indexer_missing(self, indexer, value):
21862194
# and set inplace
21872195
if self.ndim == 1:
21882196
index = self.obj.index
2189-
new_index = index.insert(len(index), indexer)
2197+
with warnings.catch_warnings():
2198+
# TODO: re-issue this with setitem-specific message?
2199+
warnings.filterwarnings(
2200+
"ignore",
2201+
"The behavior of Index.insert with object-dtype is deprecated",
2202+
category=FutureWarning,
2203+
)
2204+
new_index = index.insert(len(index), indexer)
21902205

21912206
# we have a coerced indexer, e.g. a float
21922207
# that matches in an int64 Index, so

pandas/core/internals/managers.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1376,8 +1376,14 @@ def insert(self, loc: int, item: Hashable, value: ArrayLike, refs=None) -> None:
13761376
value : np.ndarray or ExtensionArray
13771377
refs : The reference tracking object of the value to set.
13781378
"""
1379-
# insert to the axis; this could possibly raise a TypeError
1380-
new_axis = self.items.insert(loc, item)
1379+
with warnings.catch_warnings():
1380+
# TODO: re-issue this with setitem-specific message?
1381+
warnings.filterwarnings(
1382+
"ignore",
1383+
"The behavior of Index.insert with object-dtype is deprecated",
1384+
category=FutureWarning,
1385+
)
1386+
new_axis = self.items.insert(loc, item)
13811387

13821388
if value.ndim == 2:
13831389
value = value.T

pandas/tests/indexes/test_old_base.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -407,13 +407,20 @@ def test_where(self, listlike_box, simple_index):
407407
tm.assert_index_equal(result, expected)
408408

409409
def test_insert_base(self, index):
410-
result = index[1:4]
410+
trimmed = index[1:4]
411411

412412
if not len(index):
413413
pytest.skip("Not applicable for empty index")
414414

415415
# test 0th element
416-
assert index[0:4].equals(result.insert(0, index[0]))
416+
warn = None
417+
if index.dtype == object and index.inferred_type == "boolean":
418+
# GH#51363
419+
warn = FutureWarning
420+
msg = "The behavior of Index.insert with object-dtype is deprecated"
421+
with tm.assert_produces_warning(warn, match=msg):
422+
result = trimmed.insert(0, index[0])
423+
assert index[0:4].equals(result)
417424

418425
def test_insert_out_of_bounds(self, index):
419426
# TypeError/IndexError matches what np.insert raises in these cases

0 commit comments

Comments
 (0)