@@ -294,7 +294,7 @@ def _has_valid_positional_setitem_indexer(self, indexer):
294
294
295
295
return True
296
296
297
- def _setitem_with_indexer (self , indexer , value ):
297
+ def _setitem_with_indexer (self , indexer , value , columns = None ):
298
298
self ._has_valid_setitem_indexer (indexer )
299
299
300
300
# also has the side effect of consolidating in-place
@@ -304,6 +304,10 @@ def _setitem_with_indexer(self, indexer, value):
304
304
# maybe partial set
305
305
take_split_path = self .obj ._is_mixed_type
306
306
307
+ # if not all columns are present
308
+ if columns and [k for k in columns if k not in self .obj .columns ]:
309
+ take_split_path = True
310
+
307
311
# if there is only one block/type, still have to take split path
308
312
# unless the block is one-dimensional or it can hold the value
309
313
if not take_split_path and self .obj ._data .blocks :
@@ -466,10 +470,13 @@ def _setitem_with_indexer(self, indexer, value):
466
470
if isinstance (value , ABCSeries ):
467
471
value = self ._align_series (indexer , value )
468
472
469
- info_idx = indexer [info_axis ]
470
- if is_integer (info_idx ):
471
- info_idx = [info_idx ]
472
- labels = item_labels [info_idx ]
473
+ if columns is None :
474
+ info_idx = indexer [info_axis ]
475
+ if is_integer (info_idx ):
476
+ info_idx = [info_idx ]
477
+ labels = item_labels [info_idx ]
478
+ else :
479
+ labels = columns
473
480
474
481
# if we have a partial multiindex, then need to adjust the plane
475
482
# indexer here
@@ -517,6 +524,9 @@ def _setitem_with_indexer(self, indexer, value):
517
524
lplane_indexer = 0
518
525
519
526
def setter (item , v ):
527
+ if item not in self .obj .columns :
528
+ self .obj [item ] = v
529
+ return
520
530
s = self .obj [item ]
521
531
pi = plane_indexer [0 ] if lplane_indexer == 1 else plane_indexer
522
532
@@ -1109,7 +1119,8 @@ def _getitem_axis(self, key, axis=None):
1109
1119
1110
1120
return self ._get_label (key , axis = axis )
1111
1121
1112
- def _get_listlike_indexer (self , key , axis , raise_missing = False ):
1122
+ def _get_listlike_indexer (self , key , axis , is_setter = False ,
1123
+ raise_missing = False ):
1113
1124
"""
1114
1125
Transform a list-like of keys into a new index and an indexer.
1115
1126
@@ -1162,6 +1173,7 @@ def _get_listlike_indexer(self, key, axis, raise_missing=False):
1162
1173
1163
1174
self ._validate_read_indexer (keyarr , indexer ,
1164
1175
o ._get_axis_number (axis ),
1176
+ is_setter = is_setter ,
1165
1177
raise_missing = raise_missing )
1166
1178
return keyarr , indexer
1167
1179
@@ -1210,7 +1222,8 @@ def _getitem_iterable(self, key, axis=None):
1210
1222
return self .obj ._reindex_with_indexers ({axis : [keyarr , indexer ]},
1211
1223
copy = True , allow_dups = True )
1212
1224
1213
- def _validate_read_indexer (self , key , indexer , axis , raise_missing = False ):
1225
+ def _validate_read_indexer (self , key , indexer , axis , is_setter = False ,
1226
+ raise_missing = False ):
1214
1227
"""
1215
1228
Check that indexer can be used to return a result (e.g. at least one
1216
1229
element was found, unless the list of keys was actually empty).
@@ -1244,7 +1257,8 @@ def _validate_read_indexer(self, key, indexer, axis, raise_missing=False):
1244
1257
missing = (indexer < 0 ).sum ()
1245
1258
1246
1259
if missing :
1247
- if missing == len (indexer ):
1260
+ if (not (self .name == 'loc' and is_setter ) and
1261
+ missing == len (indexer )):
1248
1262
raise KeyError (
1249
1263
"None of [{key}] are in the [{axis}]" .format (
1250
1264
key = key , axis = self .obj ._get_axis_name (axis )))
@@ -1268,7 +1282,7 @@ def _validate_read_indexer(self, key, indexer, axis, raise_missing=False):
1268
1282
See the documentation here:
1269
1283
https://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike""" ) # noqa
1270
1284
1271
- if not (ax .is_categorical () or ax .is_interval ()):
1285
+ if not is_setter and not (ax .is_categorical () or ax .is_interval ()):
1272
1286
warnings .warn (_missing_key_warning ,
1273
1287
FutureWarning , stacklevel = 6 )
1274
1288
@@ -1353,8 +1367,8 @@ def _convert_to_indexer(self, obj, axis=None, is_setter=False,
1353
1367
return inds
1354
1368
else :
1355
1369
# When setting, missing keys are not allowed, even with .loc:
1356
- kwargs = {'raise_missing ' : True if is_setter else
1357
- raise_missing }
1370
+ kwargs = {'is_setter ' : is_setter ,
1371
+ 'raise_missing' : raise_missing }
1358
1372
return self ._get_listlike_indexer (obj , axis , ** kwargs )[1 ]
1359
1373
else :
1360
1374
try :
0 commit comments