From 4bc04a46cbac8caa7e2146e3efa5293fd2377da7 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Sat, 2 Jul 2022 13:54:14 +0200 Subject: [PATCH 1/2] BUG: DataFrame.loc not aligning rhs df for single block case --- doc/source/whatsnew/v1.5.0.rst | 1 + pandas/core/frame.py | 7 ++++--- pandas/tests/frame/indexing/test_indexing.py | 9 +++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 6fc1ec9c6ff90..4e22ec263289f 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -882,6 +882,7 @@ Indexing - Bug in :meth:`Series.__setitem__` when setting ``boolean`` dtype values containing ``NA`` incorrectly raising instead of casting to ``boolean`` dtype (:issue:`45462`) - Bug in :meth:`Series.__setitem__` where setting :attr:`NA` into a numeric-dtype :class:`Series` would incorrectly upcast to object-dtype rather than treating the value as ``np.nan`` (:issue:`44199`) - Bug in :meth:`DataFrame.loc` when setting values to a column and right hand side is a dictionary (:issue:`47216`) +- Bug in :meth:`DataFrame.loc` when setting a :class:`DataFrame` not aligning index in some cases (:issue:`47578`) - Bug in :meth:`Series.__setitem__` with ``datetime64[ns]`` dtype, an all-``False`` boolean mask, and an incompatible value incorrectly casting to ``object`` instead of retaining ``datetime64[ns]`` dtype (:issue:`45967`) - Bug in :meth:`Index.__getitem__` raising ``ValueError`` when indexer is from boolean dtype with ``NA`` (:issue:`45806`) - Bug in :meth:`Series.__setitem__` losing precision when enlarging :class:`Series` with scalar (:issue:`32346`) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 82ae93ad31763..75844ec8f2d3d 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4706,10 +4706,11 @@ def _sanitize_column(self, value) -> ArrayLike: """ self._ensure_valid_index(value) - # We should never get here with DataFrame value - if isinstance(value, Series): + # We can get there through isetitem with a DataFrame + # or through loc single_block_path + if isinstance(value, DataFrame): return _reindex_for_setitem(value, self.index) - elif isinstance(value, dict): + elif is_dict_like(value): return _reindex_for_setitem(Series(value), self.index) if is_list_like(value): diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index 0fbf375e441ac..994181eac8199 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -1298,6 +1298,15 @@ def test_loc_expand_empty_frame_keep_midx_names(self): ) tm.assert_frame_equal(df, expected) + @pytest.mark.parametrize("val", ["x", 1]) + @pytest.mark.parametrize("idxr", ["a", ["a"]]) + def test_loc_setitem_rhs_frame(self, idxr, val): + # GH#47578 + df = DataFrame({"a": [1, 2]}) + df.loc[:, "a"] = DataFrame({"a": [val, 11]}, index=[1, 2]) + expected = DataFrame({"a": [np.nan, val]}) + tm.assert_frame_equal(df, expected) + class TestDataFrameIndexingUInt64: def test_setitem(self, uint64_frame): From a861c95aa18e639707c62729130f28eb622bb6ea Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Sat, 2 Jul 2022 13:59:59 +0200 Subject: [PATCH 2/2] Add additional test --- pandas/tests/frame/indexing/test_setitem.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pandas/tests/frame/indexing/test_setitem.py b/pandas/tests/frame/indexing/test_setitem.py index d30121f8f6271..9e9310d735f6a 100644 --- a/pandas/tests/frame/indexing/test_setitem.py +++ b/pandas/tests/frame/indexing/test_setitem.py @@ -721,6 +721,17 @@ def test_setitem_aligning_dict_with_index(self, vals): ) tm.assert_frame_equal(df, expected) + def test_setitem_rhs_dataframe(self): + # GH#47578 + df = DataFrame({"a": [1, 2]}) + df["a"] = DataFrame({"a": [10, 11]}, index=[1, 2]) + expected = DataFrame({"a": [np.nan, 10]}) + tm.assert_frame_equal(df, expected) + + df = DataFrame({"a": [1, 2]}) + df.isetitem(0, DataFrame({"a": [10, 11]}, index=[1, 2])) + tm.assert_frame_equal(df, expected) + class TestSetitemTZAwareValues: @pytest.fixture