私は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
次に、最初の値の名前を this に変更します。
df.columns.values[0] = 'f'
すべてがとてもいいようです:
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']
b
を選択すると、正常に動作します。
print (df['b'])
0 1
1 3
2 5
Name: b, dtype: int64
ただし、a
を選択すると、列f
が返されます。
print (df['a'])
0 7
1 8
2 9
Name: f, dtype: int64
f
を選択すると、キーエラーが発生します。
print (df['f'])
#KeyError: 'f'
print (df.info())
#KeyError: 'f'
問題は何ですか?誰かがそれを説明できますか?それともバグ?
values
属性を変更することは想定されていません。
df.columns.values = ['a', 'b', 'c']
を試してみてください:
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-61-e7e440adc404> in <module>() ----> 1 df.columns.values = ['a', 'b', 'c'] AttributeError: can't set attribute
これは、属性を設定しようとしていることをpandas
が検出して停止したためです。
ただし、基になるvalues
オブジェクト自体を変更することはできます。
rename
を使用すると、pandas
が一連のクリーンアップ処理を実行します。以下のソースを貼り付けました。
最終的には、クリーンアップを開始せずに値を変更します。 _data.rename_axis
へのフォローアップコールで自分で開始できます(例は下のソースで確認できます)。これによりクリーンアップが強制的に実行され、['f']
にアクセスできます
df._data = df._data.rename_axis(lambda x: x, 0, True)
df['f']
0 7
1 8
2 9
Name: f, dtype: int64
話の教訓:この方法で列の名前を変更することは、おそらく良い考えではありません。
しかし、この話は奇妙になります
これでいい
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
これはnotで結構です
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:
結局のところ、values
を表示する前にdf
属性を変更すると、最初のdisplay
ですべての初期化が実行されるようです。 values
属性を変更する前に表示すると、エラーになります。
奇妙な静止画
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
これが悪い考えであることをまだ知らなかったかのように...
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)