Why does pandas silently ignore the .iloc [i, j] assignment with too many indexes?

Why pandas behaves differently when setting up or getting items in a series with an erroneous number of indices:

df = pd.DataFrame({'a': [10]}) # df['a'] is a series, can be indexed with 1 index only # will raise IndexingError, as expected df['a'].iloc[0, 0] df['a'].loc[0, 0] # will raise nothing, not as expected df['a'].iloc[0, 0] = 1000 # equivalent to pass df['a'].loc[0, 0] = 1000 # equivalent to df['a'].loc[0] = 1000 # pandas version 0.18.1, python 3.5 

Edit: Report .

+5
source share
1 answer

Getting Values

If the key is a tuple (as in your example), then the __getitem__ superclass method for loc and iloc at some point calls _has_valid_tuple(self, key) .

This method has the following code

 for i, k in enumerate(key): if i >= self.obj.ndim: raise IndexingError('Too many indexers') 

This raises the IndexingError that you expect.

Values

The superclass __setitem__ makes a call to _get_setitem_indexer and, in turn, _convert_to_indexer .

This implementation of the superclass _convert_to_indexer bit messy, but in this case it returns a numpy [0, 0] array.

The iLoc indexer class, however, overrides _convert_to_indexer . This method returns the original tuple ...

 def _convert_to_indexer(self, obj, axis=0, is_setter=False): ... elif self._has_valid_type(obj, axis): return obj 

The indexer variable is now a numpy array for the .loc case and a tuple for the .iloc case. This leads to a difference in behavior settings in the next superclass call to _setitem_with_indexer(indexer, value) .

+1
source

All Articles