number name index iloc column pandas numpy multiple-columns rename

pandas - name - Después de cambiar el nombre de la columna, obtenga keyerror



pandas subset (1)

Tengo df :

df = pd.DataFrame({''a'':[7,8,9], ''b'':[1,3,5], ''c'':[5,3,6]}) print (df) a b c 0 7 1 5 1 8 3 3 2 9 5 6

Luego cambie el nombre del primer valor por this :

df.columns.values[0] = ''f''

Todo parece muy lindo:

print (df) f b c 0 7 1 5 1 8 3 3 2 9 5 6 print (df.columns) Index([''f'', ''b'', ''c''], dtype=''object'') print (df.columns.values) [''f'' ''b'' ''c'']

Si selecciona b funciona bien:

print (df[''b'']) 0 1 1 3 2 5 Name: b, dtype: int64

Pero si selecciona a columna de retorno f :

print (df[''a'']) 0 7 1 8 2 9 Name: f, dtype: int64

Y si selecciona f obtenga keyerror.

print (df[''f'']) #KeyError: ''f'' print (df.info()) #KeyError: ''f''

¿Cual es el problema? ¿Alguien puede explicarlo? O error?


No se espera que altere el atributo de values .

Pruebe df.columns.values = [''a'', ''b'', ''c''] y obtendrá:

--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-61-e7e440adc404> in <module>() ----> 1 df.columns.values = [''a'', ''b'', ''c''] AttributeError: can''t set attribute

Esto se debe a que los pandas detectan que estás intentando establecer el atributo y te detienen.

Sin embargo, no puede impedir que cambie los objetos de values subyacentes en sí.

Cuando usas rename , los pandas siguen con un montón de cosas de limpieza. He pegado la fuente a continuación.

En última instancia, lo que ha hecho es alterar los valores sin iniciar la limpieza. Puede iniciarlo usted mismo con una llamada de seguimiento a _data.rename_axis (puede ver el ejemplo en la fuente a continuación). Esto obligará a ejecutar la limpieza y luego podrá acceder a [''f'']

df._data = df._data.rename_axis(lambda x: x, 0, True) df[''f''] 0 7 1 8 2 9 Name: f, dtype: int64

Moraleja de la historia: probablemente no sea una buena idea cambiar el nombre de una columna de esta manera.

pero esta historia se vuelve más rara

Esto esta bien

df = pd.DataFrame({''a'':[7,8,9], ''b'':[1,3,5], ''c'':[5,3,6]}) df.columns.values[0] = ''f'' df[''f''] 0 7 1 8 2 9 Name: f, dtype: int64

Esto no esta bien

df = pd.DataFrame({''a'':[7,8,9], ''b'':[1,3,5], ''c'':[5,3,6]}) print(df) df.columns.values[0] = ''f'' df[''f'']

KeyError:

Resulta que podemos modificar el atributo de values antes de mostrar df y aparentemente ejecutará toda la inicialización en la primera display . Si lo muestra antes de cambiar el atributo de values , se producirá un error.

aún más raro

df = pd.DataFrame({''a'':[7,8,9], ''b'':[1,3,5], ''c'':[5,3,6]}) print(df) df.columns.values[0] = ''f'' df[''f''] = 1 df[''f''] f f 0 7 1 1 8 1 2 9 1

Como si no supiéramos que era una mala idea ...

fuente para rename

def rename(self, *args, **kwargs): axes, kwargs = self._construct_axes_from_arguments(args, kwargs) copy = kwargs.pop(''copy'', True) inplace = kwargs.pop(''inplace'', False) if kwargs: raise TypeError(''rename() got an unexpected keyword '' ''argument "{0}"''.format(list(kwargs.keys())[0])) if com._count_not_none(*axes.values()) == 0: raise TypeError(''must pass an index to rename'') # renamer function if passed a dict def _get_rename_function(mapper): if isinstance(mapper, (dict, ABCSeries)): def f(x): if x in mapper: return mapper[x] else: return x else: f = mapper return f self._consolidate_inplace() result = self if inplace else self.copy(deep=copy) # start in the axis order to eliminate too many copies for axis in lrange(self._AXIS_LEN): v = axes.get(self._AXIS_NAMES[axis]) if v is None: continue f = _get_rename_function(v) baxis = self._get_block_manager_axis(axis) result._data = result._data.rename_axis(f, axis=baxis, copy=copy) result._clear_item_cache() if inplace: self._update_inplace(result._data) else: return result.__finalize__(self)