@@ -1937,24 +1937,25 @@ def _setitem_single_column(self, loc: int, value, plane_indexer):
1937
1937
pi = plane_indexer
1938
1938
1939
1939
ser = self .obj ._ixs (loc , axis = 1 )
1940
+ orig_values = ser ._values
1940
1941
1941
1942
# perform the equivalent of a setitem on the info axis
1942
1943
# as we have a null slice or a slice with full bounds
1943
1944
# which means essentially reassign to the columns of a
1944
1945
# multi-dim object
1945
1946
# GH#6149 (null slice), GH#10408 (full bounds)
1946
1947
if com .is_null_slice (pi ) or com .is_full_slice (pi , len (self .obj )):
1947
- ser = value
1948
+ pass
1948
1949
elif (
1949
1950
is_array_like (value )
1950
1951
and is_exact_shape_match (ser , value )
1951
1952
and not is_empty_indexer (pi )
1952
1953
):
1953
1954
if is_list_like (pi ):
1954
- ser = value [np .argsort (pi )]
1955
+ value = value [np .argsort (pi )]
1955
1956
else :
1956
1957
# in case of slice
1957
- ser = value [pi ]
1958
+ value = value [pi ]
1958
1959
else :
1959
1960
# set the item, first attempting to operate inplace, then
1960
1961
# falling back to casting if necessary; see
@@ -1970,8 +1971,40 @@ def _setitem_single_column(self, loc: int, value, plane_indexer):
1970
1971
self .obj ._iset_item (loc , ser )
1971
1972
return
1972
1973
1973
- # reset the sliced object if unique
1974
- self .obj ._iset_item (loc , ser )
1974
+ # We will not operate in-place, but will attempt to in the future.
1975
+ # To determine whether we need to issue a FutureWarning, see if the
1976
+ # setting in-place would work, i.e. behavior will change.
1977
+ warn = can_hold_element (ser ._values , value )
1978
+ # Don't issue the warning yet, as we can still trim a few cases where
1979
+ # behavior will not change.
1980
+
1981
+ self .obj ._iset_item (loc , value )
1982
+
1983
+ if warn :
1984
+ new_values = self .obj ._ixs (loc , axis = 1 )._values
1985
+
1986
+ if (
1987
+ isinstance (new_values , np .ndarray )
1988
+ and isinstance (orig_values , np .ndarray )
1989
+ and np .shares_memory (new_values , orig_values )
1990
+ ):
1991
+ # TODO: get something like tm.shares_memory working?
1992
+ # The values were set inplace after all, no need to warn,
1993
+ # e.g. test_rename_nocopy
1994
+ pass
1995
+ else :
1996
+ warnings .warn (
1997
+ "In a future version, `df.iloc[:, i] = newvals` will attempt "
1998
+ "to set the values inplace instead of always setting a new "
1999
+ "array. To retain the old behavior, use either "
2000
+ "`df[df.columns[i]] = newvals` or, if columns are non-unique, "
2001
+ "`df.isetitem(i, newvals)`" ,
2002
+ FutureWarning ,
2003
+ stacklevel = find_stack_level (),
2004
+ )
2005
+ # TODO: how to get future behavior?
2006
+ # TODO: what if we got here indirectly via loc?
2007
+ return
1975
2008
1976
2009
def _setitem_single_block (self , indexer , value , name : str ):
1977
2010
"""
@@ -1981,7 +2014,6 @@ def _setitem_single_block(self, indexer, value, name: str):
1981
2014
1982
2015
info_axis = self .obj ._info_axis_number
1983
2016
item_labels = self .obj ._get_axis (info_axis )
1984
-
1985
2017
if isinstance (indexer , tuple ):
1986
2018
1987
2019
# if we are setting on the info axis ONLY
@@ -1996,7 +2028,9 @@ def _setitem_single_block(self, indexer, value, name: str):
1996
2028
if len (item_labels .get_indexer_for ([col ])) == 1 :
1997
2029
# e.g. test_loc_setitem_empty_append_expands_rows
1998
2030
loc = item_labels .get_loc (col )
1999
- self .obj ._iset_item (loc , value )
2031
+ # Go through _setitem_single_column to get
2032
+ # FutureWarning if relevant.
2033
+ self ._setitem_single_column (loc , value , indexer [0 ])
2000
2034
return
2001
2035
2002
2036
indexer = maybe_convert_ix (* indexer ) # e.g. test_setitem_frame_align
0 commit comments