@@ -342,6 +342,10 @@ def test_setitem_complete_column_with_array(self):
342
342
"d" : [1 , 1 , 1 ],
343
343
}
344
344
)
345
+ expected ["c" ] = expected ["c" ].astype (arr .dtype )
346
+ expected ["d" ] = expected ["d" ].astype (arr .dtype )
347
+ assert expected ["c" ].dtype == arr .dtype
348
+ assert expected ["d" ].dtype == arr .dtype
345
349
tm .assert_frame_equal (df , expected )
346
350
347
351
@pytest .mark .parametrize ("dtype" , ["f8" , "i8" , "u8" ])
@@ -381,16 +385,35 @@ def test_setitem_frame_duplicate_columns(self, using_array_manager):
381
385
[np .nan , 1 , 2 , np .nan , 4 , 5 ],
382
386
[np .nan , 1 , 2 , np .nan , 4 , 5 ],
383
387
],
384
- columns = cols ,
385
388
dtype = "object" ,
386
389
)
390
+
387
391
if using_array_manager :
388
392
# setitem replaces column so changes dtype
393
+
394
+ expected .columns = cols
389
395
expected ["C" ] = expected ["C" ].astype ("int64" )
390
396
# TODO(ArrayManager) .loc still overwrites
391
397
expected ["B" ] = expected ["B" ].astype ("int64" )
398
+ else :
399
+ # set these with unique columns to be extra-unambiguous
400
+ expected [2 ] = expected [2 ].astype (np .int64 )
401
+ expected [5 ] = expected [5 ].astype (np .int64 )
402
+ expected .columns = cols
403
+
392
404
tm .assert_frame_equal (df , expected )
393
405
406
+ def test_setitem_frame_duplicate_columns_size_mismatch (self ):
407
+ # GH#39510
408
+ cols = ["A" , "B" , "C" ] * 2
409
+ df = DataFrame (index = range (3 ), columns = cols )
410
+ with pytest .raises (ValueError , match = "Columns must be same length as key" ):
411
+ df [["A" ]] = (0 , 3 , 5 )
412
+
413
+ df2 = df .iloc [:, :3 ] # unique columns
414
+ with pytest .raises (ValueError , match = "Columns must be same length as key" ):
415
+ df2 [["A" ]] = (0 , 3 , 5 )
416
+
394
417
@pytest .mark .parametrize ("cols" , [["a" , "b" , "c" ], ["a" , "a" , "a" ]])
395
418
def test_setitem_df_wrong_column_number (self , cols ):
396
419
# GH#38604
@@ -890,3 +913,47 @@ def test_setitem_clear_caches(self):
890
913
891
914
assert df ["z" ] is not foo
892
915
tm .assert_series_equal (df ["z" ], expected )
916
+
917
+ def test_setitem_duplicate_columns_not_inplace (self ):
918
+ # GH#39510
919
+ cols = ["A" , "B" ] * 2
920
+ df = DataFrame (0.0 , index = [0 ], columns = cols )
921
+ df_copy = df .copy ()
922
+ df_view = df [:]
923
+ df ["B" ] = (2 , 5 )
924
+
925
+ expected = DataFrame ([[0.0 , 2 , 0.0 , 5 ]], columns = cols )
926
+ tm .assert_frame_equal (df_view , df_copy )
927
+ tm .assert_frame_equal (df , expected )
928
+
929
+ @pytest .mark .parametrize ("value" , [1 , np .array ([[1 ], [1 ]]), [[1 ], [1 ]]])
930
+ def test_setitem_same_dtype_not_inplace (self , value , using_array_manager , request ):
931
+ # GH#39510
932
+ if not using_array_manager :
933
+ mark = pytest .mark .xfail (
934
+ reason = "Setitem with same dtype still changing inplace"
935
+ )
936
+ request .node .add_marker (mark )
937
+
938
+ cols = ["A" , "B" ]
939
+ df = DataFrame (0 , index = [0 , 1 ], columns = cols )
940
+ df_copy = df .copy ()
941
+ df_view = df [:]
942
+ df [["B" ]] = value
943
+
944
+ expected = DataFrame ([[0 , 1 ], [0 , 1 ]], columns = cols )
945
+ tm .assert_frame_equal (df , expected )
946
+ tm .assert_frame_equal (df_view , df_copy )
947
+
948
+ @pytest .mark .parametrize ("value" , [1.0 , np .array ([[1.0 ], [1.0 ]]), [[1.0 ], [1.0 ]]])
949
+ def test_setitem_listlike_key_scalar_value_not_inplace (self , value ):
950
+ # GH#39510
951
+ cols = ["A" , "B" ]
952
+ df = DataFrame (0 , index = [0 , 1 ], columns = cols )
953
+ df_copy = df .copy ()
954
+ df_view = df [:]
955
+ df [["B" ]] = value
956
+
957
+ expected = DataFrame ([[0 , 1.0 ], [0 , 1.0 ]], columns = cols )
958
+ tm .assert_frame_equal (df_view , df_copy )
959
+ tm .assert_frame_equal (df , expected )
0 commit comments