After rename column get keyerror

前端 未结 1 1869
一向
一向 2020-11-28 15:34

I have df:

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

print (df)
   a  b  c
0  7  1         


        
相关标签:
1条回答
  • 2020-11-28 16:14

    You aren't expected to alter the values attribute.

    Try df.columns.values = ['a', 'b', 'c'] and you get:

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

    That's because pandas detects that you are trying to set the attribute and stops you.

    However, it can't stop you from changing the underlying values object itself.

    When you use rename, pandas follows up with a bunch of clean up stuff. I've pasted the source below.

    Ultimately what you've done is altered the values without initiating the clean up. You can initiate it yourself with a followup call to _data.rename_axis (example can be seen in source below). This will force the clean up to be run and then you can access ['f']

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

    Moral of the story: probably not a great idea to rename a column this way.


    but this story gets weirder

    This is fine

    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
    

    This is not fine

    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:
    

    Turns out, we can modify the values attribute prior to displaying df and it will apparently run all the initialization upon the first display. If you display it prior to changing the values attribute, it will error out.

    weirder still

    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
    

    As if we didn't already know that this was a bad idea...


    source for 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)
    
    0 讨论(0)
提交回复
热议问题