pandas.DataFrameの列をインデックス(行名)に割り当てるset_index

Modified: | Tags: Python, pandas

pandas.DataFrameset_index()メソッドを使うと、既存の列をインデックスindex(行名、行ラベル)に割り当てることができる。インデックスに一意の名前を指定しておくと、locatで要素を選択・抽出するとき分かりやすいので便利。

反対にindexをデータ列にするにはreset_index()を使う。

indexの一部を変更したり全体をリストなどで置き換えたりする方法については以下の記事を参照。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。例として以下のデータを使用する。

import pandas as pd

print(pd.__version__)
# 2.1.4

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

set_index()の使い方

基本的な使い方

第一引数keysにインデックスとして使用する列の列名(列ラベル)を指定する。指定した列がindexに設定される。

print(df.set_index('name'))
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

指定した列をそのまま残す: 引数drop

デフォルトでは、インデックスに指定した列はデータ列から削除される。引数drop=Falseとすると、指定列がindexに設定された上でデータ列にも残る。

print(df.set_index('name', drop=False))
#             name  age state  point
# name                              
# Alice      Alice   24    NY     64
# Bob          Bob   42    CA     92
# Charlie  Charlie   18    CA     70
# Dave        Dave   68    TX     70
# Ellen      Ellen   24    CA     88
# Frank      Frank   30    NY     57

マルチインデックスを割り当て: 複数列指定、引数append

set_index()で複数の列を階層的にインデックスとするマルチインデックスを割り当てることもできる。マルチインデックスについては以下の記事を参照。

複数の列をリストで指定

第一引数keysに列名(列ラベル)のリストを指定すると、複数の列がマルチインデックスとして割り当てられる。

print(df.set_index(['state', 'name']))
#                age  point
# state name               
# NY    Alice     24     64
# CA    Bob       42     92
#       Charlie   18     70
# TX    Dave      68     70
# CA    Ellen     24     88
# NY    Frank     30     57

sort_index()でソートすると綺麗に表示される。

print(df.set_index(['state', 'name']).sort_index())
#                age  point
# state name               
# CA    Bob       42     92
#       Charlie   18     70
#       Ellen     24     88
# NY    Alice     24     64
#       Frank     30     57
# TX    Dave      68     70

指定列をインデックスの階層に追加: 引数append

デフォルトではset_index()に列を指定すると、元のインデックスは削除される。

df_name = df.set_index('name')
print(df_name)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

print(df_name.set_index('state'))
#        age  point
# state            
# NY      24     64
# CA      42     92
# CA      18     70
# TX      68     70
# CA      24     88
# NY      30     57

引数appendTrueとすると、元のインデックスに加えて、指定した列が新たな階層のインデックスとして追加される。

df_mi = df_name.set_index('state', append=True)
print(df_mi)
#                age  point
# name    state            
# Alice   NY      24     64
# Bob     CA      42     92
# Charlie CA      18     70
# Dave    TX      68     70
# Ellen   CA      24     88
# Frank   NY      30     57

追加された列は一番下の階層となる。階層を入れ替えるにはswaplevel()を使う。

print(df_mi.swaplevel(0, 1))
#                age  point
# state name               
# NY    Alice     24     64
# CA    Bob       42     92
#       Charlie   18     70
# TX    Dave      68     70
# CA    Ellen     24     88
# NY    Frank     30     57

元のインデックスを列として残す

set_index()で新しいインデックスを指定すると元のインデックスは削除される。

元のインデックスを残すには、インデックスを0始まりの連番に振り直すreset_index()を使う。

df_name = df.set_index('name')
print(df_name)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

print(df_name.reset_index())
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

インデックスを別の列に変更(再設定)するにはreset_index()のあとでset_index()を用いればよい。一気に書くと以下のようになる。

print(df_name.reset_index().set_index('state'))
#           name  age  point
# state                     
# NY       Alice   24     64
# CA         Bob   42     92
# CA     Charlie   18     70
# TX        Dave   68     70
# CA       Ellen   24     88
# NY       Frank   30     57

新しいインデックスに重複がないかチェック: 引数verify_integrity

デフォルトでは、新しいインデックスに重複があってもそのまま使用される。引数verify_integrityTrueとすると、重複があるとエラーになる。

print(df.set_index('state'))
#           name  age  point
# state                     
# NY       Alice   24     64
# CA         Bob   42     92
# CA     Charlie   18     70
# TX        Dave   68     70
# CA       Ellen   24     88
# NY       Frank   30     57

# print(df.set_index('state', verify_integrity=True))
# ValueError: Index has duplicate keys: Index(['CA', 'NY'], dtype='object', name='state')

元のオブジェクトを変更: 引数inplace

デフォルトではset_index()で元のオブジェクトは変更されず、新たなオブジェクトが返される。引数inplaceTrueとすると、元のオブジェクトが変更される。

df.set_index('name', inplace=True)
print(df)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

CSVファイルなどの読み込み時にインデックスを指定

pd.read_csv()でCSVファイルをDataFrameとして読み込むときにインデックスとする列を指定できる。引数index_colに列番号を指定するとその列がインデックスとなる。

df_name = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df_name)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

インデックス(行名)を使って行や要素を選択・抽出

インデックス(行名、行ラベル)に一意の文字列などを指定すると、行や要素を名前で選択・抽出できる。

df_name = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df_name)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

print(df_name.loc['Bob'])
# age      42
# state    CA
# point    92
# Name: Bob, dtype: object

print(df_name.at['Bob', 'age'])
# 42

atlocによる要素や行・列の選択、インデックス指定による行・列の選択についての詳細は以下の記事を参照。

関連カテゴリー

関連記事