@@ -681,7 +681,7 @@ def __setitem__(self, key, value):
681
681
self ._has_valid_setitem_indexer (key )
682
682
683
683
iloc = self if self .name == "iloc" else self .obj .iloc
684
- iloc ._setitem_with_indexer (indexer , value )
684
+ iloc ._setitem_with_indexer (indexer , value , self . name )
685
685
686
686
def _validate_key (self , key , axis : int ):
687
687
"""
@@ -1517,7 +1517,7 @@ def _get_setitem_indexer(self, key):
1517
1517
1518
1518
# -------------------------------------------------------------------
1519
1519
1520
- def _setitem_with_indexer (self , indexer , value ):
1520
+ def _setitem_with_indexer (self , indexer , value , name = "iloc" ):
1521
1521
"""
1522
1522
_setitem_with_indexer is for setting values on a Series/DataFrame
1523
1523
using positional indexers.
@@ -1593,7 +1593,7 @@ def _setitem_with_indexer(self, indexer, value):
1593
1593
new_indexer = convert_from_missing_indexer_tuple (
1594
1594
indexer , self .obj .axes
1595
1595
)
1596
- self ._setitem_with_indexer (new_indexer , value )
1596
+ self ._setitem_with_indexer (new_indexer , value , name )
1597
1597
1598
1598
return
1599
1599
@@ -1624,11 +1624,11 @@ def _setitem_with_indexer(self, indexer, value):
1624
1624
# align and set the values
1625
1625
if take_split_path :
1626
1626
# We have to operate column-wise
1627
- self ._setitem_with_indexer_split_path (indexer , value )
1627
+ self ._setitem_with_indexer_split_path (indexer , value , name )
1628
1628
else :
1629
- self ._setitem_single_block (indexer , value )
1629
+ self ._setitem_single_block (indexer , value , name )
1630
1630
1631
- def _setitem_with_indexer_split_path (self , indexer , value ):
1631
+ def _setitem_with_indexer_split_path (self , indexer , value , name : str ):
1632
1632
"""
1633
1633
Setitem column-wise.
1634
1634
"""
@@ -1642,7 +1642,7 @@ def _setitem_with_indexer_split_path(self, indexer, value):
1642
1642
if isinstance (indexer [0 ], np .ndarray ) and indexer [0 ].ndim > 2 :
1643
1643
raise ValueError (r"Cannot set values with ndim > 2" )
1644
1644
1645
- if isinstance (value , ABCSeries ):
1645
+ if isinstance (value , ABCSeries ) and name != "iloc" :
1646
1646
value = self ._align_series (indexer , value )
1647
1647
1648
1648
# Ensure we have something we can iterate over
@@ -1657,7 +1657,7 @@ def _setitem_with_indexer_split_path(self, indexer, value):
1657
1657
if is_list_like_indexer (value ) and getattr (value , "ndim" , 1 ) > 0 :
1658
1658
1659
1659
if isinstance (value , ABCDataFrame ):
1660
- self ._setitem_with_indexer_frame_value (indexer , value )
1660
+ self ._setitem_with_indexer_frame_value (indexer , value , name )
1661
1661
1662
1662
elif np .ndim (value ) == 2 :
1663
1663
self ._setitem_with_indexer_2d_value (indexer , value )
@@ -1714,7 +1714,7 @@ def _setitem_with_indexer_2d_value(self, indexer, value):
1714
1714
# setting with a list, re-coerces
1715
1715
self ._setitem_single_column (loc , value [:, i ].tolist (), pi )
1716
1716
1717
- def _setitem_with_indexer_frame_value (self , indexer , value : "DataFrame" ):
1717
+ def _setitem_with_indexer_frame_value (self , indexer , value : "DataFrame" , name : str ):
1718
1718
ilocs = self ._ensure_iterable_column_indexer (indexer [1 ])
1719
1719
1720
1720
sub_indexer = list (indexer )
@@ -1724,7 +1724,13 @@ def _setitem_with_indexer_frame_value(self, indexer, value: "DataFrame"):
1724
1724
1725
1725
unique_cols = value .columns .is_unique
1726
1726
1727
- if not unique_cols and value .columns .equals (self .obj .columns ):
1727
+ # We do not want to align the value in case of iloc GH#37728
1728
+ if name == "iloc" :
1729
+ for i , loc in enumerate (ilocs ):
1730
+ val = value .iloc [:, i ]
1731
+ self ._setitem_single_column (loc , val , pi )
1732
+
1733
+ elif not unique_cols and value .columns .equals (self .obj .columns ):
1728
1734
# We assume we are already aligned, see
1729
1735
# test_iloc_setitem_frame_duplicate_columns_multiple_blocks
1730
1736
for loc in ilocs :
@@ -1787,7 +1793,7 @@ def _setitem_single_column(self, loc: int, value, plane_indexer):
1787
1793
# reset the sliced object if unique
1788
1794
self .obj ._iset_item (loc , ser )
1789
1795
1790
- def _setitem_single_block (self , indexer , value ):
1796
+ def _setitem_single_block (self , indexer , value , name : str ):
1791
1797
"""
1792
1798
_setitem_with_indexer for the case when we have a single Block.
1793
1799
"""
@@ -1815,14 +1821,13 @@ def _setitem_single_block(self, indexer, value):
1815
1821
return
1816
1822
1817
1823
indexer = maybe_convert_ix (* indexer )
1818
-
1819
- if isinstance (value , (ABCSeries , dict )):
1824
+ if isinstance (value , ABCSeries ) and name != "iloc" or isinstance (value , dict ):
1820
1825
# TODO(EA): ExtensionBlock.setitem this causes issues with
1821
1826
# setting for extensionarrays that store dicts. Need to decide
1822
1827
# if it's worth supporting that.
1823
1828
value = self ._align_series (indexer , Series (value ))
1824
1829
1825
- elif isinstance (value , ABCDataFrame ):
1830
+ elif isinstance (value , ABCDataFrame ) and name != "iloc" :
1826
1831
value = self ._align_frame (indexer , value )
1827
1832
1828
1833
# check for chained assignment
@@ -1854,7 +1859,7 @@ def _setitem_with_indexer_missing(self, indexer, value):
1854
1859
if index .is_unique :
1855
1860
new_indexer = index .get_indexer ([new_index [- 1 ]])
1856
1861
if (new_indexer != - 1 ).any ():
1857
- return self ._setitem_with_indexer (new_indexer , value )
1862
+ return self ._setitem_with_indexer (new_indexer , value , "loc" )
1858
1863
1859
1864
# this preserves dtype of the value
1860
1865
new_values = Series ([value ])._values
0 commit comments