追加 - python インデックス 名 変更




Pandas の列の名前を変更する (19)

オリジナルの列ラベルを置き換えるために編集する必要のあるパンダと列ラベルを使用しているDataFrameがあります。

元の列名があるDataFrame A列名を変更したいのですが:

['$a', '$b', '$c', '$d', '$e'] 

['a', 'b', 'c', 'd', 'e'].

編集した列名がリストに格納されていますが、列名を置き換える方法はわかりません。


1つのラインまたはパイプラインソリューション

私は2つのことに焦点を当てます:

  1. OP明確に状態

    編集した列名がリストに格納されていますが、列名を置き換える方法はわかりません。

    私は'$'を置き換えるか、各列ヘッダーの最初の文字を取り除く方法の問題を解決したくありません。 OPは既にこのステップを行っています。 代わりに、既存のcolumnsオブジェクトを置き換える列名のリストを与えられた新しいcolumnsオブジェクトに置き換えることに集中したいと思います。

  2. df.columns = newここで、 newは新しい列名のリストです。 このアプローチの欠点は、既存のデータフレームのcolumns属性を編集する必要があり、インラインで行われないことです。 既存のデータフレームを編集せずにパイプライン処理でこれを実行する方法をいくつか示します。

セットアップ1
既存のリストで列名を置き換える名前を変更する必要性に焦点を当てるために、最初の列名と無関係な新しい列名を持つ新しいサンプルデータフレームdfを作成します。

df = pd.DataFrame({'Jack': [1, 2], 'Mahesh': [3, 4], 'Xin': [5, 6]})
new = ['x098', 'y765', 'z432']

df

   Jack  Mahesh  Xin
0     1       3    5
1     2       4    6

解決策1
pd.DataFrame.rename

以前の列名を新しい列名にマッピングする辞書があればpd.DataFrame.rename使用することができます。

d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'}
df.rename(columns=d)

   x098  y765  z432
0     1     3     5
1     2     4     6

ただし、その辞書を簡単に作成し、 renamerenameための呼び出しに含めることは簡単です。 以下は、 dfを反復処理するときに各列名に対して反復処理を行うという事実を利用しています。

# given just a list of new column names
df.rename(columns=dict(zip(df, new)))

   x098  y765  z432
0     1     3     5
1     2     4     6

元の列名が一意である場合、これは効果的です。 しかし、そうでなければ、これは崩壊する。

セットアップ2
ユニークでない列

df = pd.DataFrame(
    [[1, 3, 5], [2, 4, 6]],
    columns=['Mahesh', 'Mahesh', 'Xin']
)
new = ['x098', 'y765', 'z432']

df

   Mahesh  Mahesh  Xin
0       1       3    5
1       2       4    6

解決策2
keys引数を使用するpd.concat

まず、ソリューション1を使用しようとすると何が起こるのかを確認します。

df.rename(columns=dict(zip(df, new)))

   y765  y765  z432
0     1     3     5
1     2     4     6

newリストを列名としてマッピングしませんでした。 私たちはy765繰り返すことにy765 。 代わりに、 pd.concat関数のkeys引数を使用してdfの列を反復することができます。

pd.concat([c for _, c in df.items()], axis=1, keys=new) 

   x098  y765  z432
0     1     3     5
1     2     4     6

ソリューション3
再構築する。 これは、すべての列に対して単一のdtypeがある場合にのみ使用してください。 それ以外の場合は、すべての列に対してdtype objectdtypeされ、それらを変換するにはさらに辞書作業が必要になります。

シングルdtype

pd.DataFrame(df.values, df.index, new)

   x098  y765  z432
0     1     3     5
1     2     4     6

混合dtype

pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

ソリューション4
これは、 transposeset_indexを使った奇妙なトリックset_indexpd.DataFrame.set_index使用すると、インデックスをインラインに設定できますが、対応するset_columnsはありません。 だから私たちは転置し、次にset_indexと転置することができます。 ただし、ソリューション3の同じdtype対mixed dtype警告がここで適用されます。

シングルdtype

df.T.set_index(np.asarray(new)).T

   x098  y765  z432
0     1     3     5
1     2     4     6

混合dtype

df.T.set_index(np.asarray(new)).T.astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

解決策5
pd.DataFrame.rename lambdaを使用して、 new要素の各要素を循環させます
この解法では、 xを受け取り、無視するラムダを渡します。 それはまたy取るがそれを期待しない。 代わりに、イテレータがデフォルト値として与えられ、それを使って、 xの値が何であるかに関係なく、一度に1つずつサイクルを繰り返すことができます。

df.rename(columns=lambda x, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

また、 sopythonのチャットで私が指摘したように、 xy間に*を追加すると、 y変数を保護することができます。 この文脈では、私はそれが保護を必要としているとは思わない。 それはまだ言及する価値があります。

df.rename(columns=lambda x, *, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

DataFrame - df.rename()が動作します。

df.rename(columns = {'Old Name':'New Name'})

dfは所有しているDataFrameで、 Old Nameは変更する列名です。新しい名前は変更する新しい名前です。 このDataFrameビルトインメソッドにより、作業が非常に簡単になります。


パンダ0.21+回答

バージョン0.21では列の名前変更にいくつかの重要な更新がありました。

  • renameメソッドは、 axisまたは1設定されるaxisパラメータを追加しました。 このアップデートにより、このメソッドは他のpandas APIと一致します。 これには引き続きindexcolumnsパラメータがありますが、もはや強制的に使用する必要はありません。
  • set_axisFalse設定したset_axisメソッドを使用すると、すべてのインデックスまたはカラムのラベルの名前をリストで変更できます。

パンダ0.21 +の例

サンプルのDataFrameを構築する:

df = pd.DataFrame({'$a':[1,2], '$b': [3,4], 
                   '$c':[5,6], '$d':[7,8], 
                   '$e':[9,10]})

   $a  $b  $c  $d  $e
0   1   3   5   7   9
1   2   4   6   8  10

renameaxis='columns'またはaxis=1

df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')

または

df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis=1)

どちらも次のようになります。

   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10

古いメソッドのシグネチャを使用することはまだ可能です。

df.rename(columns={'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'})

rename機能は、各列名に適用される機能も受け入れます。

df.rename(lambda x: x[1:], axis='columns')

または

df.rename(lambda x: x[1:], axis=1)

リストとset_axis inplace=False set_axisを使う

カラム数(またはインデックス)と同じ長さのリストをset_axisメソッドにset_axisことができます。 現在、 inplaceデフォルトはTrueですが、 inplaceは将来のリリースではFalseにデフォルト設定されます。

df.set_axis(['a', 'b', 'c', 'd', 'e'], axis='columns', inplace=False)

または

df.set_axis(['a', 'b', 'c', 'd', 'e'], axis=1, inplace=False)

なぜdf.columns = ['a', 'b', 'c', 'd', 'e']ないのですか?

このように列を直接割り当てることには何も問題はありません。 それは完全に良い解決策です。

set_axisを使用する利点は、メソッドチェーンの一部として使用でき、DataFrameの新しいコピーを返すことです。 それがなければ、列の再割り当ての前にチェーンの中間ステップを別の変数に格納する必要があります。

# 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()

df.rename()メソッドは、次のような関数をとることができます。

In [11]: df.columns
Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object)

In [12]: df.rename(columns=lambda x: x[1:], inplace=True)

In [13]: df.columns
Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)


.columns属性に割り当てるだけです:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20

あなたがデータフレームを持っていれば、df.columnsはすべてをリストにダンプし、操作してデータフレームに列の名前として再割り当てできます...

columns = df.columns
columns = [row.replace("$","") for row in columns]
df.rename(columns=dict(zip(columns, things)), inplace=True)
df.head() #to validate the output

最良の方法? IDK。 方法 - はい。

質問への答えに出てくる主なテクニックを評価するより良い方法は、cProfileを使ってメモリと実行時間をゲージすることです。 @kadee、@kaitlyn、および@eumiroは実行時間が最も速い関数を持っていましたが、これらの関数は非常に高速ですが、すべての答えに対して.000と.001秒の丸めを比較しています。 道徳:上の私の答えは、おそらく "ベスト"方法ではありません。

import pandas as pd
import cProfile, pstats, re

old_names = ['$a', '$b', '$c', '$d', '$e']
new_names = ['a', 'b', 'c', 'd', 'e']
col_dict = {'$a': 'a', '$b': 'b','$c':'c','$d':'d','$e':'e'}

df = pd.DataFrame({'$a':[1,2], '$b': [10,20],'$c':['bleep','blorp'],'$d':[1,2],'$e':['texa$','']})

df.head()

def eumiro(df,nn):
    df.columns = nn
    #This direct renaming approach is duplicated in methodology in several other answers: 
    return df

def lexual1(df):
    return df.rename(columns=col_dict)

def lexual2(df,col_dict):
    return df.rename(columns=col_dict, inplace=True)

def Panda_Master_Hayden(df):
    return df.rename(columns=lambda x: x[1:], inplace=True)

def paulo1(df):
    return df.rename(columns=lambda x: x.replace('$', ''))

def paulo2(df):
    return df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

def migloo(df,on,nn):
    return df.rename(columns=dict(zip(on, nn)), inplace=True)

def kadee(df):
    return df.columns.str.replace('$','')

def awo(df):
    columns = df.columns
    columns = [row.replace("$","") for row in columns]
    return df.rename(columns=dict(zip(columns, '')), inplace=True)

def kaitlyn(df):
    df.columns = [col.strip('$') for col in df.columns]
    return df

print 'eumiro'
cProfile.run('eumiro(df,new_names)')
print 'lexual1'
cProfile.run('lexual1(df)')
print 'lexual2'
cProfile.run('lexual2(df,col_dict)')
print 'andy hayden'
cProfile.run('Panda_Master_Hayden(df)')
print 'paulo1'
cProfile.run('paulo1(df)')
print 'paulo2'
cProfile.run('paulo2(df)')
print 'migloo'
cProfile.run('migloo(df,old_names,new_names)')
print 'kadee'
cProfile.run('kadee(df)')
print 'awo'
cProfile.run('awo(df)')
print 'kaitlyn'
cProfile.run('kaitlyn(df)')

あなたはそれのためにstr.sliceを使うことができます:

df.columns = df.columns.str.slice(1)

これらのアプローチはMultiIndexでは機能しません。 MultiIndexの場合は、次のような処理が必要です。

>>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]})
>>> df
   $a $b  e
   $x $y  f
0  1  3  5
1  2  4  6
>>> rename = {('$a','$x'):('a','x'), ('$b','$y'):('b','y')}
>>> df.columns = pandas.MultiIndex.from_tuples([
        rename.get(item, item) for item in df.columns.tolist()])
>>> df
   a  b  e
   x  y  f
0  1  3  5
1  2  4  6

これを試して。 わたしにはできる

df.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})

オリジナルの列ラベルを置き換える別の方法は、元の列ラベルから不要な文字(ここでは '$')を取り除くことです。

これは、df.columns上でforループを実行し、削除された列をdf.columnsに追加することで実行できます。

代わりに、以下のようなリストの理解を使用して、単一のステートメントできれいにこれを行うことができます:

df.columns = [col.strip('$') for col in df.columns]

(Pythonのstripメソッドは、文字列の先頭と最後の文字をstripます)。


別のオプションは、正規表現を使用して名前を変更することです。

import pandas as pd
import re

df = pd.DataFrame({'$a':[1,2], '$b':[3,4], '$c':[5,6]})

df = df.rename(columns=lambda x: re.sub('\$','',x))
>>> df
   a  b  c
0  1  3  5
1  2  4  6

本当のシンプルな使い方

df.columns = ['Name1', 'Name2', 'Name3'...]

それを置く順序で列名を割り当てます


私はこのメソッドが便利だと思う:

df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})

このメソッドを使用すると、列名を個別に変更できます。


行名df.columns = ['a', 'b',index=False]を使用しない場合はdf.columns = ['a', 'b',index=False]


Renaming columns while reading the Dataframe: 

>>> df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1]}).rename(columns = 
         {'$a' : 'a','$b':'b','$c':'c'})

Out[1]: 
   a  b  c
0  1  1  1

df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

新しい列のリストが既存の列と同じ順序である場合、割り当ては簡単です。

new_cols = ['a', 'b', 'c', 'd', 'e']
df.columns = new_cols
>>> df
   a  b  c  d  e
0  1  1  1  1  1

古い列名に新しい列名をキー入力した辞書がある場合は、次の操作を実行できます。

d = {'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}
df.columns = df.columns.map(lambda col: d[col])  # Or `.map(d.get)` as pointed out by @PiRSquared.
>>> df
   a  b  c  d  e
0  1  1  1  1  1

リストまたは辞書のマッピングがない場合は、リスト内包を介して先頭の$記号を取り除くことができます。

df.columns = [col[1:] if col[0] == '$' else col for col in df]

df.columns = ['a', 'b', 'c', 'd', 'e']

既存の名前が指定した名前に置き換えられます。


old_names = ['$a', '$b', '$c', '$d', '$e'] 
new_names = ['a', 'b', 'c', 'd', 'e']
df.rename(columns=dict(zip(old_names, new_names)), inplace=True)

このようにして、 new_namesを手動で編集することができます。 いくつかの列の名前を変更して間違いやアクセントを修正したり、特殊文字を削除したりする必要があるときに効果的です。





rename