9
9
import numpy as np
10
10
import pytest
11
11
12
+ from pandas ._libs import iNaT
12
13
from pandas .errors import InvalidIndexError
13
14
14
15
from pandas .core .dtypes .common import is_integer
24
25
Timestamp ,
25
26
date_range ,
26
27
isna ,
28
+ notna ,
27
29
to_datetime ,
28
30
)
29
31
import pandas ._testing as tm
@@ -830,6 +832,15 @@ def test_setitem_single_column_mixed_datetime(self):
830
832
)
831
833
tm .assert_series_equal (result , expected )
832
834
835
+ # GH#16674 iNaT is treated as an integer when given by the user
836
+ with tm .assert_produces_warning (
837
+ FutureWarning , match = "Setting an item of incompatible dtype"
838
+ ):
839
+ df .loc ["b" , "timestamp" ] = iNaT
840
+ assert not isna (df .loc ["b" , "timestamp" ])
841
+ assert df ["timestamp" ].dtype == np .object_
842
+ assert df .loc ["b" , "timestamp" ] == iNaT
843
+
833
844
# allow this syntax (as of GH#3216)
834
845
df .loc ["c" , "timestamp" ] = np .nan
835
846
assert isna (df .loc ["c" , "timestamp" ])
@@ -838,6 +849,38 @@ def test_setitem_single_column_mixed_datetime(self):
838
849
df .loc ["d" , :] = np .nan
839
850
assert not isna (df .loc ["c" , :]).all ()
840
851
852
+ def test_setitem_mixed_datetime (self ):
853
+ # GH 9336
854
+ expected = DataFrame (
855
+ {
856
+ "a" : [0 , 0 , 0 , 0 , 13 , 14 ],
857
+ "b" : [
858
+ datetime (2012 , 1 , 1 ),
859
+ 1 ,
860
+ "x" ,
861
+ "y" ,
862
+ datetime (2013 , 1 , 1 ),
863
+ datetime (2014 , 1 , 1 ),
864
+ ],
865
+ }
866
+ )
867
+ df = DataFrame (0 , columns = list ("ab" ), index = range (6 ))
868
+ df ["b" ] = pd .NaT
869
+ df .loc [0 , "b" ] = datetime (2012 , 1 , 1 )
870
+ with tm .assert_produces_warning (
871
+ FutureWarning , match = "Setting an item of incompatible dtype"
872
+ ):
873
+ df .loc [1 , "b" ] = 1
874
+ df .loc [[2 , 3 ], "b" ] = "x" , "y"
875
+ A = np .array (
876
+ [
877
+ [13 , np .datetime64 ("2013-01-01T00:00:00" )],
878
+ [14 , np .datetime64 ("2014-01-01T00:00:00" )],
879
+ ]
880
+ )
881
+ df .loc [[4 , 5 ], ["a" , "b" ]] = A
882
+ tm .assert_frame_equal (df , expected )
883
+
841
884
def test_setitem_frame_float (self , float_frame ):
842
885
piece = float_frame .loc [float_frame .index [:2 ], ["A" , "B" ]]
843
886
float_frame .loc [float_frame .index [- 2 ] :, ["A" , "B" ]] = piece .values
@@ -889,6 +932,17 @@ def test_setitem_frame_mixed_ndarray(self, float_string_frame):
889
932
f .loc [key ] = piece .values
890
933
tm .assert_almost_equal (f .loc [f .index [- 2 :], ["A" , "B" ]].values , piece .values )
891
934
935
+ def test_setitem_frame_upcast (self ):
936
+ # needs upcasting
937
+ df = DataFrame ([[1 , 2 , "foo" ], [3 , 4 , "bar" ]], columns = ["A" , "B" , "C" ])
938
+ df2 = df .copy ()
939
+ with tm .assert_produces_warning (FutureWarning , match = "incompatible dtype" ):
940
+ df2 .loc [:, ["A" , "B" ]] = df .loc [:, ["A" , "B" ]] + 0.5
941
+ expected = df .reindex (columns = ["A" , "B" ])
942
+ expected += 0.5
943
+ expected ["C" ] = df ["C" ]
944
+ tm .assert_frame_equal (df2 , expected )
945
+
892
946
def test_setitem_frame_align (self , float_frame ):
893
947
piece = float_frame .loc [float_frame .index [:2 ], ["A" , "B" ]]
894
948
piece .index = float_frame .index [- 2 :]
@@ -1299,6 +1353,26 @@ def test_loc_expand_empty_frame_keep_midx_names(self):
1299
1353
)
1300
1354
tm .assert_frame_equal (df , expected )
1301
1355
1356
+ @pytest .mark .parametrize (
1357
+ "val, idxr" ,
1358
+ [
1359
+ ("x" , "a" ),
1360
+ ("x" , ["a" ]),
1361
+ (1 , "a" ),
1362
+ (1 , ["a" ]),
1363
+ ],
1364
+ )
1365
+ def test_loc_setitem_rhs_frame (self , idxr , val ):
1366
+ # GH#47578
1367
+ df = DataFrame ({"a" : [1 , 2 ]})
1368
+
1369
+ with tm .assert_produces_warning (
1370
+ FutureWarning , match = "Setting an item of incompatible dtype"
1371
+ ):
1372
+ df .loc [:, idxr ] = DataFrame ({"a" : [val , 11 ]}, index = [1 , 2 ])
1373
+ expected = DataFrame ({"a" : [np .nan , val ]})
1374
+ tm .assert_frame_equal (df , expected )
1375
+
1302
1376
def test_iloc_setitem_enlarge_no_warning (self ):
1303
1377
# GH#47381
1304
1378
df = DataFrame (columns = ["a" , "b" ])
@@ -1502,6 +1576,22 @@ def test_setitem(self):
1502
1576
tm .assert_series_equal (df ["D" ], Series (idx , name = "D" ))
1503
1577
del df ["D" ]
1504
1578
1579
+ # With NaN: because uint64 has no NaN element,
1580
+ # the column should be cast to object.
1581
+ df2 = df .copy ()
1582
+ with tm .assert_produces_warning (FutureWarning , match = "incompatible dtype" ):
1583
+ df2 .iloc [1 , 1 ] = pd .NaT
1584
+ df2 .iloc [1 , 2 ] = pd .NaT
1585
+ result = df2 ["B" ]
1586
+ tm .assert_series_equal (notna (result ), Series ([True , False , True ], name = "B" ))
1587
+ tm .assert_series_equal (
1588
+ df2 .dtypes ,
1589
+ Series (
1590
+ [np .dtype ("uint64" ), np .dtype ("O" ), np .dtype ("O" )],
1591
+ index = ["A" , "B" , "C" ],
1592
+ ),
1593
+ )
1594
+
1505
1595
1506
1596
def test_object_casting_indexing_wraps_datetimelike ():
1507
1597
# GH#31649, check the indexing methods all the way down the stack
@@ -1836,31 +1926,22 @@ def test_add_new_column_infer_string():
1836
1926
class TestSetitemValidation :
1837
1927
# This is adapted from pandas/tests/arrays/masked/test_indexing.py
1838
1928
# but checks for warnings instead of errors.
1839
- def _check_setitem_invalid (self , df , invalid , indexer ):
1929
+ def _check_setitem_invalid (self , df , invalid , indexer , warn ):
1930
+ msg = "Setting an item of incompatible dtype is deprecated"
1931
+ msg = re .escape (msg )
1932
+
1840
1933
orig_df = df .copy ()
1841
1934
1842
1935
# iloc
1843
- with pytest . raises ( TypeError , match = "Invalid value" ):
1936
+ with tm . assert_produces_warning ( warn , match = msg ):
1844
1937
df .iloc [indexer , 0 ] = invalid
1845
1938
df = orig_df .copy ()
1846
1939
1847
1940
# loc
1848
- with pytest . raises ( TypeError , match = "Invalid value" ):
1941
+ with tm . assert_produces_warning ( warn , match = msg ):
1849
1942
df .loc [indexer , "a" ] = invalid
1850
1943
df = orig_df .copy ()
1851
1944
1852
- def _check_setitem_valid (self , df , invalid , indexer ):
1853
- # Just execute, verify no error is raised
1854
- orig_df = df .copy ()
1855
-
1856
- # iloc
1857
- df .iloc [indexer , 0 ] = invalid
1858
- df = orig_df .copy ()
1859
-
1860
- # loc
1861
- df .loc [indexer , "a" ] = invalid
1862
- df = orig_df .copy ()
1863
-
1864
1945
_invalid_scalars = [
1865
1946
1 + 2j ,
1866
1947
"True" ,
@@ -1878,19 +1959,20 @@ def _check_setitem_valid(self, df, invalid, indexer):
1878
1959
@pytest .mark .parametrize ("indexer" , _indexers )
1879
1960
def test_setitem_validation_scalar_bool (self , invalid , indexer ):
1880
1961
df = DataFrame ({"a" : [True , False , False ]}, dtype = "bool" )
1881
- self ._check_setitem_invalid (df , invalid , indexer )
1962
+ self ._check_setitem_invalid (df , invalid , indexer , FutureWarning )
1882
1963
1883
1964
@pytest .mark .parametrize ("invalid" , _invalid_scalars + [True , 1.5 , np .float64 (1.5 )])
1884
1965
@pytest .mark .parametrize ("indexer" , _indexers )
1885
1966
def test_setitem_validation_scalar_int (self , invalid , any_int_numpy_dtype , indexer ):
1886
1967
df = DataFrame ({"a" : [1 , 2 , 3 ]}, dtype = any_int_numpy_dtype )
1887
1968
if isna (invalid ) and invalid is not pd .NaT and not np .isnat (invalid ):
1888
- self . _check_setitem_valid ( df , invalid , indexer )
1969
+ warn = None
1889
1970
else :
1890
- self ._check_setitem_invalid (df , invalid , indexer )
1971
+ warn = FutureWarning
1972
+ self ._check_setitem_invalid (df , invalid , indexer , warn )
1891
1973
1892
1974
@pytest .mark .parametrize ("invalid" , _invalid_scalars + [True ])
1893
1975
@pytest .mark .parametrize ("indexer" , _indexers )
1894
1976
def test_setitem_validation_scalar_float (self , invalid , float_numpy_dtype , indexer ):
1895
1977
df = DataFrame ({"a" : [1 , 2 , None ]}, dtype = float_numpy_dtype )
1896
- self ._check_setitem_invalid (df , invalid , indexer )
1978
+ self ._check_setitem_invalid (df , invalid , indexer , FutureWarning )
0 commit comments