@@ -335,12 +335,18 @@ def test_setitem(self, float_frame, using_copy_on_write):
335
335
def test_setitem2 (self ):
336
336
# dtype changing GH4204
337
337
df = DataFrame ([[0 , 0 ]])
338
- df .iloc [0 ] = np .nan
338
+ with tm .assert_produces_warning (
339
+ FutureWarning , match = "Setting an item of incompatible dtype"
340
+ ):
341
+ df .iloc [0 ] = np .nan
339
342
expected = DataFrame ([[np .nan , np .nan ]])
340
343
tm .assert_frame_equal (df , expected )
341
344
342
345
df = DataFrame ([[0 , 0 ]])
343
- df .loc [0 ] = np .nan
346
+ with tm .assert_produces_warning (
347
+ FutureWarning , match = "Setting an item of incompatible dtype"
348
+ ):
349
+ df .loc [0 ] = np .nan
344
350
tm .assert_frame_equal (df , expected )
345
351
346
352
def test_setitem_boolean (self , float_frame ):
@@ -1332,12 +1338,22 @@ def test_loc_expand_empty_frame_keep_midx_names(self):
1332
1338
)
1333
1339
tm .assert_frame_equal (df , expected )
1334
1340
1335
- @pytest .mark .parametrize ("val" , ["x" , 1 ])
1336
- @pytest .mark .parametrize ("idxr" , ["a" , ["a" ]])
1337
- def test_loc_setitem_rhs_frame (self , idxr , val ):
1341
+ @pytest .mark .parametrize (
1342
+ "val, idxr, warn" ,
1343
+ [
1344
+ ("x" , "a" , None ), # TODO: this should warn as well
1345
+ ("x" , ["a" ], None ), # TODO: this should warn as well
1346
+ (1 , "a" , None ), # TODO: this should warn as well
1347
+ (1 , ["a" ], FutureWarning ),
1348
+ ],
1349
+ )
1350
+ def test_loc_setitem_rhs_frame (self , idxr , val , warn ):
1338
1351
# GH#47578
1339
1352
df = DataFrame ({"a" : [1 , 2 ]})
1340
- with tm .assert_produces_warning (None ):
1353
+
1354
+ with tm .assert_produces_warning (
1355
+ warn , match = "Setting an item of incompatible dtype"
1356
+ ):
1341
1357
df .loc [:, idxr ] = DataFrame ({"a" : [val , 11 ]}, index = [1 , 2 ])
1342
1358
expected = DataFrame ({"a" : [np .nan , val ]})
1343
1359
tm .assert_frame_equal (df , expected )
@@ -1537,8 +1553,11 @@ def test_setitem(self, uint64_frame):
1537
1553
# With NaN: because uint64 has no NaN element,
1538
1554
# the column should be cast to object.
1539
1555
df2 = df .copy ()
1540
- df2 .iloc [1 , 1 ] = pd .NaT
1541
- df2 .iloc [1 , 2 ] = pd .NaT
1556
+ with tm .assert_produces_warning (
1557
+ FutureWarning , match = "Setting an item of incompatible dtype"
1558
+ ):
1559
+ df2 .iloc [1 , 1 ] = pd .NaT
1560
+ df2 .iloc [1 , 2 ] = pd .NaT
1542
1561
result = df2 ["B" ]
1543
1562
tm .assert_series_equal (notna (result ), Series ([True , False , True ], name = "B" ))
1544
1563
tm .assert_series_equal (
@@ -1851,3 +1870,54 @@ def test_setitem_dict_and_set_disallowed_multiindex(self, key):
1851
1870
)
1852
1871
with pytest .raises (TypeError , match = "as an indexer is not supported" ):
1853
1872
df .loc [key ] = 1
1873
+
1874
+
1875
+ class TestSetitemValidation :
1876
+ # This is adapted from pandas/tests/arrays/masked/test_indexing.py
1877
+ # but checks for warnings instead of errors.
1878
+ def _check_setitem_invalid (self , df , invalid , indexer ):
1879
+ msg = "Setting an item of incompatible dtype is deprecated"
1880
+ msg = re .escape (msg )
1881
+
1882
+ orig_df = df .copy ()
1883
+
1884
+ # iloc
1885
+ with tm .assert_produces_warning (FutureWarning , match = msg ):
1886
+ df .iloc [indexer , 0 ] = invalid
1887
+ df = orig_df .copy ()
1888
+
1889
+ # loc
1890
+ with tm .assert_produces_warning (FutureWarning , match = msg ):
1891
+ df .loc [indexer , "a" ] = invalid
1892
+ df = orig_df .copy ()
1893
+
1894
+ _invalid_scalars = [
1895
+ 1 + 2j ,
1896
+ "True" ,
1897
+ "1" ,
1898
+ "1.0" ,
1899
+ pd .NaT ,
1900
+ np .datetime64 ("NaT" ),
1901
+ np .timedelta64 ("NaT" ),
1902
+ ]
1903
+ _indexers = [0 , [0 ], slice (0 , 1 ), [True , False , False ]]
1904
+
1905
+ @pytest .mark .parametrize (
1906
+ "invalid" , _invalid_scalars + [1 , 1.0 , np .int64 (1 ), np .float64 (1 )]
1907
+ )
1908
+ @pytest .mark .parametrize ("indexer" , _indexers )
1909
+ def test_setitem_validation_scalar_bool (self , invalid , indexer ):
1910
+ df = DataFrame ({"a" : [True , False , False ]}, dtype = "bool" )
1911
+ self ._check_setitem_invalid (df , invalid , indexer )
1912
+
1913
+ @pytest .mark .parametrize ("invalid" , _invalid_scalars + [True , 1.5 , np .float64 (1.5 )])
1914
+ @pytest .mark .parametrize ("indexer" , _indexers )
1915
+ def test_setitem_validation_scalar_int (self , invalid , any_int_numpy_dtype , indexer ):
1916
+ df = DataFrame ({"a" : [1 , 2 , 3 ]}, dtype = any_int_numpy_dtype )
1917
+ self ._check_setitem_invalid (df , invalid , indexer )
1918
+
1919
+ @pytest .mark .parametrize ("invalid" , _invalid_scalars + [True ])
1920
+ @pytest .mark .parametrize ("indexer" , _indexers )
1921
+ def test_setitem_validation_scalar_float (self , invalid , float_numpy_dtype , indexer ):
1922
+ df = DataFrame ({"a" : [1 , 2 , None ]}, dtype = float_numpy_dtype )
1923
+ self ._check_setitem_invalid (df , invalid , indexer )
0 commit comments