From bdb111d208c51961a4bfb4be623f7052c9f1e58e Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Sun, 11 Dec 2022 00:15:57 +0100 Subject: [PATCH 1/3] BUG: isetitem coercing df columns to object --- doc/source/whatsnew/v2.0.0.rst | 1 + pandas/core/frame.py | 9 +++++++ pandas/tests/frame/indexing/test_setitem.py | 30 +++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index d6e0bb2ae0830..9eb480081aaf1 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -755,6 +755,7 @@ Indexing - Bug in :meth:`DataFrame.reindex` casting dtype to ``object`` when :class:`DataFrame` has single extension array column when re-indexing ``columns`` and ``index`` (:issue:`48190`) - Bug in :func:`~DataFrame.describe` when formatting percentiles in the resulting index showed more decimals than needed (:issue:`46362`) - Bug in :meth:`DataFrame.compare` does not recognize differences when comparing ``NA`` with value in nullable dtypes (:issue:`48939`) +- Bug in :meth:`DataFrame.isetitem` coercing extension array dtypes in :class:`DataFrame` to object (:issue:`49922`) - Missing diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c50c6faf89f8a..13661e83092e5 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -3959,6 +3959,15 @@ def isetitem(self, loc, value) -> None: In cases where `frame.columns` is unique, this is equivalent to `frame[frame.columns[i]] = value`. """ + if isinstance(value, DataFrame): + if is_scalar(loc): + loc = [loc] + + for i, idx in enumerate(loc): + arraylike = self._sanitize_column(value.iloc[:, i]) + self._iset_item_mgr(idx, arraylike, inplace=False) + return + arraylike = self._sanitize_column(value) self._iset_item_mgr(loc, arraylike, inplace=False) diff --git a/pandas/tests/frame/indexing/test_setitem.py b/pandas/tests/frame/indexing/test_setitem.py index e27f9fe9995ad..d2425ad533b58 100644 --- a/pandas/tests/frame/indexing/test_setitem.py +++ b/pandas/tests/frame/indexing/test_setitem.py @@ -741,6 +741,36 @@ def test_setitem_rhs_dataframe(self): df.isetitem(0, DataFrame({"a": [10, 11]}, index=[1, 2])) tm.assert_frame_equal(df, expected) + def test_isetitem_ea_df(self): + # GH#49922 + df = DataFrame([[1, 2, 3], [4, 5, 6]]) + rhs = DataFrame([[11, 12], [13, 14]], dtype="Int64") + + df.isetitem([0, 1], rhs) + expected = DataFrame( + { + 0: Series([11, 13], dtype="Int64"), + 1: Series([12, 14], dtype="Int64"), + 2: [3, 6], + } + ) + tm.assert_frame_equal(df, expected) + + def test_isetitem_ea_df_scalar_indexer(self): + # GH#49922 + df = DataFrame([[1, 2, 3], [4, 5, 6]]) + rhs = DataFrame([[11], [13]], dtype="Int64") + + df.isetitem(0, rhs) + expected = DataFrame( + { + 0: Series([11, 13], dtype="Int64"), + 1: [2, 5], + 2: [3, 6], + } + ) + tm.assert_frame_equal(df, expected) + def test_setitem_frame_overwrite_with_ea_dtype(self, any_numeric_ea_dtype): # GH#46896 df = DataFrame(columns=["a", "b"], data=[[1, 2], [3, 4]]) From 14c9e715b0ff30b3d2eafbad0fa9fc952719ea2b Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Fri, 30 Dec 2022 16:05:34 +0100 Subject: [PATCH 2/3] Adjust test --- pandas/tests/frame/indexing/test_setitem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/frame/indexing/test_setitem.py b/pandas/tests/frame/indexing/test_setitem.py index 5e09a5600ed7e..b966a8a3abcdd 100644 --- a/pandas/tests/frame/indexing/test_setitem.py +++ b/pandas/tests/frame/indexing/test_setitem.py @@ -748,12 +748,12 @@ def test_isetitem_ea_df_scalar_indexer(self): df = DataFrame([[1, 2, 3], [4, 5, 6]]) rhs = DataFrame([[11], [13]], dtype="Int64") - df.isetitem(0, rhs) + df.isetitem(2, rhs) expected = DataFrame( { - 0: Series([11, 13], dtype="Int64"), + 0: [1, 4], 1: [2, 5], - 2: [3, 6], + 2: Series([11, 13], dtype="Int64"), } ) tm.assert_frame_equal(df, expected) From 847d20286820f85e18626ecff9eededacd9cf173 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Tue, 3 Jan 2023 22:52:55 +0100 Subject: [PATCH 3/3] Move to new file --- pandas/tests/frame/indexing/test_setitem.py | 30 ----------------- pandas/tests/frame/methods/test_isetitem.py | 37 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 30 deletions(-) create mode 100644 pandas/tests/frame/methods/test_isetitem.py diff --git a/pandas/tests/frame/indexing/test_setitem.py b/pandas/tests/frame/indexing/test_setitem.py index b966a8a3abcdd..7b3d0382d7b01 100644 --- a/pandas/tests/frame/indexing/test_setitem.py +++ b/pandas/tests/frame/indexing/test_setitem.py @@ -728,36 +728,6 @@ def test_setitem_rhs_dataframe(self): df.isetitem(0, DataFrame({"a": [10, 11]}, index=[1, 2])) tm.assert_frame_equal(df, expected) - def test_isetitem_ea_df(self): - # GH#49922 - df = DataFrame([[1, 2, 3], [4, 5, 6]]) - rhs = DataFrame([[11, 12], [13, 14]], dtype="Int64") - - df.isetitem([0, 1], rhs) - expected = DataFrame( - { - 0: Series([11, 13], dtype="Int64"), - 1: Series([12, 14], dtype="Int64"), - 2: [3, 6], - } - ) - tm.assert_frame_equal(df, expected) - - def test_isetitem_ea_df_scalar_indexer(self): - # GH#49922 - df = DataFrame([[1, 2, 3], [4, 5, 6]]) - rhs = DataFrame([[11], [13]], dtype="Int64") - - df.isetitem(2, rhs) - expected = DataFrame( - { - 0: [1, 4], - 1: [2, 5], - 2: Series([11, 13], dtype="Int64"), - } - ) - tm.assert_frame_equal(df, expected) - def test_setitem_frame_overwrite_with_ea_dtype(self, any_numeric_ea_dtype): # GH#46896 df = DataFrame(columns=["a", "b"], data=[[1, 2], [3, 4]]) diff --git a/pandas/tests/frame/methods/test_isetitem.py b/pandas/tests/frame/methods/test_isetitem.py new file mode 100644 index 0000000000000..59328aafefefb --- /dev/null +++ b/pandas/tests/frame/methods/test_isetitem.py @@ -0,0 +1,37 @@ +from pandas import ( + DataFrame, + Series, +) +import pandas._testing as tm + + +class TestDataFrameSetItem: + def test_isetitem_ea_df(self): + # GH#49922 + df = DataFrame([[1, 2, 3], [4, 5, 6]]) + rhs = DataFrame([[11, 12], [13, 14]], dtype="Int64") + + df.isetitem([0, 1], rhs) + expected = DataFrame( + { + 0: Series([11, 13], dtype="Int64"), + 1: Series([12, 14], dtype="Int64"), + 2: [3, 6], + } + ) + tm.assert_frame_equal(df, expected) + + def test_isetitem_ea_df_scalar_indexer(self): + # GH#49922 + df = DataFrame([[1, 2, 3], [4, 5, 6]]) + rhs = DataFrame([[11], [13]], dtype="Int64") + + df.isetitem(2, rhs) + expected = DataFrame( + { + 0: [1, 4], + 1: [2, 5], + 2: Series([11, 13], dtype="Int64"), + } + ) + tm.assert_frame_equal(df, expected)