dataframeにdata
という名前をつけました。1列しかないヘッダーの名前を変更するにはどうしたらいいでしょうか?例えば、gdp
をlog(gdp)
に?
data =
y gdp cap
0 1 2 5
1 2 3 9
2 8 7 2
3 3 4 7
4 6 7 7
5 4 8 3
6 8 2 8
7 9 9 10
8 6 6 4
9 10 10 7
data.rename(columns={'gdp':'log(gdp)'}, inplace=True)
rename](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html#pandas.DataFrame.rename)を見ると、
columns`のパラメータとしてdictを受け付けるので、1つのエントリを持つdictを渡すだけです。
また、relatedも参照してください。
1つのカラムの名前を変更する必要がある場合には、list-comprehension
を使用する方がはるかに高速な実装になります。
df.columns = ['log(gdp)' if x=='gdp' else x for x in df.columns]
複数のカラムの名前を変更する必要がある場合は、次のような条件式を使用します。
df.columns = ['log(gdp)' if x=='gdp' else 'cap_mod' if x=='cap' else x for x in df.columns]
あるいは、dictionary
を使ってマッピングを構築し、その get
操作で list-comprehension
を実行し、デフォルト値を古い名前に設定します。
col_dict = {'gdp': 'log(gdp)', 'cap': 'cap_mod'} ## key→old name, value→new name
df.columns = [col_dict.get(x, x) for x in df.columns]
タイミング:。
%%timeit
df.rename(columns={'gdp':'log(gdp)'}, inplace=True)
10000 loops, best of 3: 168 µs per loop
%%timeit
df.columns = ['log(gdp)' if x=='gdp' else x for x in df.columns]
10000 loops, best of 3: 58.5 µs per loop
pandasで特定の列の名前を変更するには?
v0.24+より、一度に1つ(または複数)のカラムの名前を変更するようになりました。
DataFrame.rename()
でaxis=1
またはaxis='columns'
(axis
引数はv0.21
で導入されました。
Index.str.replace()
文字列/正規表現ベースの置換を行います。
一度にすべての列の名前を変更する必要がある場合。
DataFrame.set_axis()
メソッドで、axis=1
を指定します。リストのような配列を渡します。インプレースでの変更にもオプションが用意されています。rename
に axis=1
を指定します。df = pd.DataFrame('x', columns=['y', 'gdp', 'cap'], index=range(5))
df
y gdp cap
0 x x x
1 x x x
2 x x x
3 x x x
4 x x x
0.21+ で rename
で axis
パラメータを指定できるようになりました。
df.rename({'gdp':'log(gdp)'}, axis=1)
# df.rename({'gdp':'log(gdp)'}, axis='columns')
y log(gdp) cap
0 x x x
1 x x x
2 x x x
3 x x x
4 x x x
(ただし、rename
はデフォルトではインプレースされないので、結果を 代入 する必要があります。)
この追加は、他のAPIとの整合性を高めるために行われました。新しい axis
引数は columns
パラメータと似ていて、同じことをします。
df.rename(columns={'gdp': 'log(gdp)'})
y log(gdp) cap
0 x x x
1 x x x
2 x x x
3 x x x
4 x x x
rename` には、各カラムに対して一度だけ呼び出されるコールバックもあります。
df.rename(lambda x: x[0], axis=1)
# df.rename(lambda x: x[0], axis='columns')
y g c
0 x x x
1 x x x
2 x x x
3 x x x
4 x x x
この具体的なシナリオでは
df.rename(lambda x: 'log(gdp)' if x == 'gdp' else x, axis=1)
Index.str.replace
pythonの文字列のreplace
メソッドと同様に、pandasのIndexとSeries(object dtypeのみ)では、文字列と正規表現ベースの置換のために、("vectorized") str.replace
メソッドを定義しています。
df.columns = df.columns.str.replace('gdp', 'log(gdp)')
df
y log(gdp) cap
0 x x x
1 x x x
2 x x x
3 x x x
4 x x x
他のメソッドと比較した場合の利点は、str.replace
が正規表現をサポートしていることです (デフォルトで有効になっています)。詳細はドキュメントを参照してください。
set_axis
に axis=1
を指定してリストを渡す。ヘッダーのリストを指定して、set_axis
を呼び出します。リストはカラム/インデックスのサイズと同じ長さでなければなりません。set_axisはデフォルトでは元の DataFrame を変更しますが、
inplace=False` を指定することで、変更されたコピーを返すことができます。
df.set_axis(['cap', 'log(gdp)', 'y'], axis=1, inplace=False)
# df.set_axis(['cap', 'log(gdp)', 'y'], axis='columns', inplace=False)
cap log(gdp) y
0 x x x
1 x x x
2 x x x
3 x x x
4 x x x
注意: 今後のリリースでは、inplace
のデフォルトは True
になります。
メソッドの連鎖。
すでに df.columns = ...
で列を割り当てる効率的な方法があるのに、なぜ set_axis
を選ぶのでしょうか?Ted Petrou氏が[この回答]で示しているように、(https://stackoverflow.com/a/46912050/4909087) set_axis
はメソッドを連鎖させようとするときに便利です。
比較
# new for pandas 0.21+
df.some_method1()
.some_method2()
.set_axis()
.some_method3()
バーサス
# old way
df1 = df.some_method1()
.some_method2()
df1.columns = columns
df1.some_method3()
前者の方がより自然で自由な構文です。