Skip to content

Commit ee6a062

Browse files
authored
DEPR: Disallow dtype inference when setting Index into DataFrame (#56102)
1 parent a61c556 commit ee6a062

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

doc/source/whatsnew/v2.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ Other Deprecations
458458
- 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`)
459459
- Deprecated casting non-datetimelike values (mainly strings) in :meth:`Series.isin` and :meth:`Index.isin` with ``datetime64``, ``timedelta64``, and :class:`PeriodDtype` dtypes (:issue:`53111`)
460460
- 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`)
461+
- Deprecated dtype inference when setting a :class:`Index` into a :class:`DataFrame`, cast explicitly instead (:issue:`56102`)
461462
- 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`)
462463
- Deprecated indexing an :class:`Index` with a boolean indexer of length zero (:issue:`55820`)
463464
- Deprecated not passing a tuple to :class:`.DataFrameGroupBy.get_group` or :class:`.SeriesGroupBy.get_group` when grouping by a length-1 list-like (:issue:`25971`)

pandas/core/frame.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -5219,7 +5219,21 @@ def _sanitize_column(self, value) -> tuple[ArrayLike, BlockValuesRefs | None]:
52195219

52205220
if is_list_like(value):
52215221
com.require_length_match(value, self.index)
5222-
return sanitize_array(value, self.index, copy=True, allow_2d=True), None
5222+
arr = sanitize_array(value, self.index, copy=True, allow_2d=True)
5223+
if (
5224+
isinstance(value, Index)
5225+
and value.dtype == "object"
5226+
and arr.dtype != value.dtype
5227+
): #
5228+
# TODO: Remove kludge in sanitize_array for string mode when enforcing
5229+
# this deprecation
5230+
warnings.warn(
5231+
"Setting an Index with object dtype into a DataFrame will no longer "
5232+
"infer another dtype. Cast the Index explicitly before setting.",
5233+
FutureWarning,
5234+
stacklevel=find_stack_level(),
5235+
)
5236+
return arr, None
52235237

52245238
@property
52255239
def _series(self):

pandas/tests/frame/indexing/test_setitem.py

+18
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,24 @@ def test_loc_setitem_ea_dtype(self):
786786
df.iloc[:, 0] = Series([11], dtype="Int64")
787787
tm.assert_frame_equal(df, expected)
788788

789+
def test_setitem_object_inferring(self):
790+
# GH#56102
791+
idx = Index([Timestamp("2019-12-31")], dtype=object)
792+
df = DataFrame({"a": [1]})
793+
with tm.assert_produces_warning(FutureWarning, match="infer"):
794+
df.loc[:, "b"] = idx
795+
with tm.assert_produces_warning(FutureWarning, match="infer"):
796+
df["c"] = idx
797+
798+
expected = DataFrame(
799+
{
800+
"a": [1],
801+
"b": Series([Timestamp("2019-12-31")], dtype="datetime64[ns]"),
802+
"c": Series([Timestamp("2019-12-31")], dtype="datetime64[ns]"),
803+
}
804+
)
805+
tm.assert_frame_equal(df, expected)
806+
789807

790808
class TestSetitemTZAwareValues:
791809
@pytest.fixture

0 commit comments

Comments
 (0)