pandasの特定の列の名前を変更する

dataframeにdataという名前をつけました。1列しかないヘッダーの名前を変更するにはどうしたらいいでしょうか?例えば、gdplog(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も参照してください。

解説 (10)

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
解説 (0)

pandasで特定の列の名前を変更するには?

v0.24+より、一度に1つ(または複数)のカラムの名前を変更するようになりました。

一度にすべての列の名前を変更する必要がある場合。

  • DataFrame.set_axis() メソッドで、axis=1を指定します。リストのような配列を渡します。インプレースでの変更にもオプションが用意されています。

renameaxis=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+ で renameaxis パラメータを指定できるようになりました。

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_axisaxis=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()

前者の方がより自然で自由な構文です。

解説 (0)