@@ -294,7 +294,7 @@ def _has_valid_positional_setitem_indexer(self, indexer):
294294
295295 return True
296296
297- def _setitem_with_indexer (self , indexer , value ):
297+ def _setitem_with_indexer (self , indexer , value , columns = None ):
298298 self ._has_valid_setitem_indexer (indexer )
299299
300300 # also has the side effect of consolidating in-place
@@ -304,6 +304,11 @@ def _setitem_with_indexer(self, indexer, value):
304304 # maybe partial set
305305 take_split_path = self .obj ._is_mixed_type
306306
307+ # if not all columns are present
308+ if (columns is not None and
309+ any (k not in self .obj .columns for k in columns )):
310+ take_split_path = True
311+
307312 # if there is only one block/type, still have to take split path
308313 # unless the block is one-dimensional or it can hold the value
309314 if not take_split_path and self .obj ._data .blocks :
@@ -466,10 +471,13 @@ def _setitem_with_indexer(self, indexer, value):
466471 if isinstance (value , ABCSeries ):
467472 value = self ._align_series (indexer , value )
468473
469- info_idx = indexer [info_axis ]
470- if is_integer (info_idx ):
471- info_idx = [info_idx ]
472- labels = item_labels [info_idx ]
474+ if columns is None :
475+ info_idx = indexer [info_axis ]
476+ if is_integer (info_idx ):
477+ info_idx = [info_idx ]
478+ labels = item_labels [info_idx ]
479+ else :
480+ labels = columns
473481
474482 # if we have a partial multiindex, then need to adjust the plane
475483 # indexer here
@@ -517,6 +525,9 @@ def _setitem_with_indexer(self, indexer, value):
517525 lplane_indexer = 0
518526
519527 def setter (item , v ):
528+ if item not in self .obj .columns :
529+ self .obj [item ] = v
530+ return
520531 s = self .obj [item ]
521532 pi = plane_indexer [0 ] if lplane_indexer == 1 else plane_indexer
522533
@@ -1109,7 +1120,8 @@ def _getitem_axis(self, key, axis=None):
11091120
11101121 return self ._get_label (key , axis = axis )
11111122
1112- def _get_listlike_indexer (self , key , axis , raise_missing = False ):
1123+ def _get_listlike_indexer (self , key , axis , is_setter = False ,
1124+ raise_missing = False ):
11131125 """
11141126 Transform a list-like of keys into a new index and an indexer.
11151127
@@ -1162,6 +1174,7 @@ def _get_listlike_indexer(self, key, axis, raise_missing=False):
11621174
11631175 self ._validate_read_indexer (keyarr , indexer ,
11641176 o ._get_axis_number (axis ),
1177+ is_setter = is_setter ,
11651178 raise_missing = raise_missing )
11661179 return keyarr , indexer
11671180
@@ -1210,7 +1223,8 @@ def _getitem_iterable(self, key, axis=None):
12101223 return self .obj ._reindex_with_indexers ({axis : [keyarr , indexer ]},
12111224 copy = True , allow_dups = True )
12121225
1213- def _validate_read_indexer (self , key , indexer , axis , raise_missing = False ):
1226+ def _validate_read_indexer (self , key , indexer , axis , is_setter = False ,
1227+ raise_missing = False ):
12141228 """
12151229 Check that indexer can be used to return a result (e.g. at least one
12161230 element was found, unless the list of keys was actually empty).
@@ -1244,7 +1258,8 @@ def _validate_read_indexer(self, key, indexer, axis, raise_missing=False):
12441258 missing = (indexer < 0 ).sum ()
12451259
12461260 if missing :
1247- if missing == len (indexer ):
1261+ if (not (self .name == 'loc' and is_setter ) and
1262+ missing == len (indexer )):
12481263 raise KeyError (
12491264 "None of [{key}] are in the [{axis}]" .format (
12501265 key = key , axis = self .obj ._get_axis_name (axis )))
@@ -1268,7 +1283,7 @@ def _validate_read_indexer(self, key, indexer, axis, raise_missing=False):
12681283 See the documentation here:
12691284 https://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike""" ) # noqa
12701285
1271- if not (ax .is_categorical () or ax .is_interval ()):
1286+ if not is_setter and not (ax .is_categorical () or ax .is_interval ()):
12721287 warnings .warn (_missing_key_warning ,
12731288 FutureWarning , stacklevel = 6 )
12741289
@@ -1353,8 +1368,8 @@ def _convert_to_indexer(self, obj, axis=None, is_setter=False,
13531368 return inds
13541369 else :
13551370 # When setting, missing keys are not allowed, even with .loc:
1356- kwargs = {'raise_missing ' : True if is_setter else
1357- raise_missing }
1371+ kwargs = {'is_setter ' : is_setter ,
1372+ 'raise_missing' : raise_missing }
13581373 return self ._get_listlike_indexer (obj , axis , ** kwargs )[1 ]
13591374 else :
13601375 try :
0 commit comments