From e9a92567666b3d423d5bc19f93e59555b511a3fd Mon Sep 17 00:00:00 2001 From: roeimed0 Date: Sun, 8 Feb 2026 22:16:13 +0200 Subject: [PATCH 1/2] BUG: loc setitem with duplicate columns and new columns corrupts DataFrame (#58317) --- doc/source/whatsnew/v3.1.0.rst | 3 +++ pandas/core/indexing.py | 3 +-- pandas/tests/indexing/test_loc.py | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v3.1.0.rst b/doc/source/whatsnew/v3.1.0.rst index 0cbb3db24c946..db5c7bcb301d9 100644 --- a/doc/source/whatsnew/v3.1.0.rst +++ b/doc/source/whatsnew/v3.1.0.rst @@ -267,6 +267,9 @@ Indexing - Bug in :meth:`Index.get_level_values` mishandling boolean, NA-like (``np.nan``, ``pd.NA``, ``pd.NaT``) and integer index names (:issue:`62169`) - Bug in :meth:`Index.get_loc` raising ``KeyError`` when looking up a tuple in an object-dtype :class:`Index` with duplicates (:issue:`37800`) - Bug in :meth:`Index.insert` silently casting booleans to numeric when used with nullable numeric dtypes like ``Float64`` or ``Int64`` (:issue:`61709`) +- Fixed bug in :meth:`DataFrame.loc` where assigning with duplicate column names and new columns corrupted unrelated columns (:issue:`58317`) +- + Missing ^^^^^^^ diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 0c14c9c925803..8bccee80d7415 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -913,8 +913,7 @@ def _ensure_listlike_indexer(self, key, axis=None) -> None: # below would create float64 columns in this example, which # would successfully hold 7, so we would end up with the wrong # dtype. - indexer = np.arange(len(keys), dtype=np.intp) - indexer[len(self.obj.columns) :] = -1 + indexer = self.obj.columns.get_indexer(keys) new_mgr = self.obj._mgr.reindex_indexer( keys, indexer=indexer, axis=0, only_slice=True, use_na_proxy=True ) diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index ef3d4797fc82a..f0ebaee79bdd9 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -2395,6 +2395,25 @@ def test_loc_setitem_with_expansion_new_row_and_new_columns(self): "D": [np.nan, np.nan, np.nan, 91.0], }, index=Index([0, 1, 2, "x"]), + def test_loc_setitem_with_expansion_duplicate_columns(self): + # GH#58317 + df = DataFrame( + [[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]], + columns=["D", "B", "C", "A"], + ) + item = DataFrame( + [[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]], + columns=["A", "B", "C", "X"], + index=[3, 2, 1], + ) + df.loc[[True, False, True], ["B", "E", "B"]] = item + expected = DataFrame( + [ + [1, np.nan, np.nan, 3, 4, np.nan], + [4, 5.0, 5.0, 6, 7, np.nan], + [7, 5.0, 5.0, 9, 10, np.nan], + ], + columns=["D", "B", "B", "C", "A", "E"], ) tm.assert_frame_equal(df, expected) From e4e23b30f43f86518ba1e0a20fbdb4f501f00a3e Mon Sep 17 00:00:00 2001 From: roeimed0 Date: Mon, 13 Apr 2026 17:17:57 +0300 Subject: [PATCH 2/2] FIX: add missing closing paren in test_loc_setitem_with_expansion_new_row_and_new_columns --- pandas/tests/indexing/test_loc.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index f0ebaee79bdd9..a5898f3f52183 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -2395,6 +2395,9 @@ def test_loc_setitem_with_expansion_new_row_and_new_columns(self): "D": [np.nan, np.nan, np.nan, 91.0], }, index=Index([0, 1, 2, "x"]), + ) + tm.assert_frame_equal(df, expected) + def test_loc_setitem_with_expansion_duplicate_columns(self): # GH#58317 df = DataFrame(