pandasのMultiindexの指定・追加・解除・ソート・レベル変更

pandasでMultiindex(マルチインデックス、階層型インデックス)を設定すると、print()表示が見やすくなったり、各階層の項目ごとの統計量を簡単に算出できたりして便利。

ここでは、マルチインデックスの設定に関して以下の内容を説明します。

ファイルの読み込み時に設定: read_csv() データ列をマルチインデックスに指定・追加: set_index() マルチインデックスを解除: reset_index() マルチインデックスをソート: sort_index() マルチインデックスのレベルを変更: swaplevel()

例として以下のデータを使用します。

import pandas as pd

df = pd.read_csv('data/src/sample_multi.csv')
print(df)
#    level_1 level_2 level_3  val_1  val_2
# 0       A0      B0      C0     98     90
# 1       A0      B0      C1     44      9
# 2       A0      B1      C2     39     17
# 3       A0      B1      C3     75     71
# 4       A1      B2      C0      1     89
# 5       A1      B2      C1     54     60
# 6       A1      B3      C2     47      6
# 7       A1      B3      C3     16      5
# 8       A2      B0      C0     75     22
# 9       A2      B0      C1     19      4
# 10      A2      B1      C2     25     52
# 11      A2      B1      C3     57     40
# 12      A3      B2      C0     64     54
# 13      A3      B2      C1     27     96
# 14      A3      B3      C2    100     77
# 15      A3      B3      C3     22     50

csvファイルはコチラ。

sample_multi.csv

ファイルの読み込み時に設定: read_csv()

ファイルからデータを読み込むのであれば、読み込み時にマルチインデックスを設定できます。 read_csv()メソッドでは、引数index_colに列名か列番号をリストで指定するとマルチインデックスになる。

df_m_csv = pd.read_csv('data/src/sample_multi.csv', index_col=['level_1', 'level_2', 'level_3'])
print(df_m_csv)
#                          val_1  val_2
# level_1 level_2 level_3              
# A0      B0      C0          98     90
#                 C1          44      9
#         B1      C2          39     17
#                 C3          75     71
# A1      B2      C0           1     89
#                 C1          54     60
#         B3      C2          47      6
#                 C3          16      5
# A2      B0      C0          75     22
#                 C1          19      4
#         B1      C2          25     52
#                 C3          57     40
# A3      B2      C0          64     54
#                 C1          27     96
#         B3      C2         100     77
#                 C3          22     50

read_csv()メソッドについての詳細は以下の記事を参照。

データ列をマルチインデックスを指定・追加: set_index()

既存のpandas.DataFrameオブジェクトの複数のデータ列をマルチインデックスとして指定するにはset_index()メソッドを使います。 第一引数keysに列名のリストを指定します。

df_m = df.set_index(['level_1', 'level_2', 'level_3'])
print(df_m)
#                          val_1  val_2
# level_1 level_2 level_3              
# A0      B0      C0          98     90
#                 C1          44      9
#         B1      C2          39     17
#                 C3          75     71
# A1      B2      C0           1     89
#                 C1          54     60
#         B3      C2          47      6
#                 C3          16      5
# A2      B0      C0          75     22
#                 C1          19      4
#         B1      C2          25     52
#                 C3          57     40
# A3      B2      C0          64     54
#                 C1          27     96
#         B3      C2         100     77
#                 C3          22     50

既にインデックスが指定されているpandas.DataFrameオブジェクトにデータ列をマルチインデックスとして追加する場合もset_index()。 引数appendをTrueとすると追加される。デフォルトはappend=Falseで新しいインデックスで上書きされてしまうので注意。

df_m_1 = df.set_index('level_1')
print(df_m_1)
#         level_2 level_3  val_1  val_2
# level_1                              
# A0           B0      C0     98     90
# A0           B0      C1     44      9
# A0           B1      C2     39     17
# A0           B1      C3     75     71
# A1           B2      C0      1     89
# A1           B2      C1     54     60
# A1           B3      C2     47      6
# A1           B3      C3     16      5
# A2           B0      C0     75     22
# A2           B0      C1     19      4
# A2           B1      C2     25     52
# A2           B1      C3     57     40
# A3           B2      C0     64     54
# A3           B2      C1     27     96
# A3           B3      C2    100     77
# A3           B3      C3     22     50

df_m_2 = df_m_1.set_index('level_2', append=True)
print(df_m_2)
#                 level_3  val_1  val_2
# level_1 level_2                      
# A0      B0           C0     98     90
#         B0           C1     44      9
#         B1           C2     39     17
#         B1           C3     75     71
# A1      B2           C0      1     89
#         B2           C1     54     60
#         B3           C2     47      6
#         B3           C3     16      5
# A2      B0           C0     75     22
#         B0           C1     19      4
#         B1           C2     25     52
#         B1           C3     57     40
# A3      B2           C0     64     54
#         B2           C1     27     96
#         B3           C2    100     77
#         B3           C3     22     50

例では新たなオブジェクトが返されているが、set_index()の引数inplaceをTrueとすると、set_index()を呼び出したオブジェクト自体が変更される。 set_index()については以下の記事も参照。

マルチインデックスを解除: reset_index()

マルチインデックスを解除するにはreset_index()メソッドを使います。 引数をなにも指定しないとすべてのインデックス列が解除され、データ列に追加される。

df_r_all = df_m.reset_index()
print(df_r_all)
#    level_1 level_2 level_3  val_1  val_2
# 0       A0      B0      C0     98     90
# 1       A0      B0      C1     44      9
# 2       A0      B1      C2     39     17
# 3       A0      B1      C3     75     71
# 4       A1      B2      C0      1     89
# 5       A1      B2      C1     54     60
# 6       A1      B3      C2     47      6
# 7       A1      B3      C3     16      5
# 8       A2      B0      C0     75     22
# 9       A2      B0      C1     19      4
# 10      A2      B1      C2     25     52
# 11      A2      B1      C3     57     40
# 12      A3      B2      C0     64     54
# 13      A3      B2      C1     27     96
# 14      A3      B3      C2    100     77
# 15      A3      B3      C3     22     50

特定のインデックス列のみをマルチインデックスから解除したい場合は、引数levelに列名を文字列で指定するかレベル(階層)を整数値で指定します。レベル(階層)は外側(大項目)が0。 列名またはレベル値のリストで指定すると複数のインデックス列が解除される。

df_r_1 = df_m.reset_index(level='level_1')
print(df_r_1)
#                 level_1  val_1  val_2
# level_2 level_3                      
# B0      C0           A0     98     90
#         C1           A0     44      9
# B1      C2           A0     39     17
#         C3           A0     75     71
# B2      C0           A1      1     89
#         C1           A1     54     60
# B3      C2           A1     47      6
#         C3           A1     16      5
# B0      C0           A2     75     22
#         C1           A2     19      4
# B1      C2           A2     25     52
#         C3           A2     57     40
# B2      C0           A3     64     54
#         C1           A3     27     96
# B3      C2           A3    100     77
#         C3           A3     22     50

df_r_1 = df_m.reset_index(level=0)
print(df_r_1)
#                 level_1  val_1  val_2
# level_2 level_3                      
# B0      C0           A0     98     90
#         C1           A0     44      9
# B1      C2           A0     39     17
#         C3           A0     75     71
# B2      C0           A1      1     89
#         C1           A1     54     60
# B3      C2           A1     47      6
#         C3           A1     16      5
# B0      C0           A2     75     22
#         C1           A2     19      4
# B1      C2           A2     25     52
#         C3           A2     57     40
# B2      C0           A3     64     54
#         C1           A3     27     96
# B3      C2           A3    100     77
#         C3           A3     22     50

df_r_2 = df_m.reset_index(level=['level_1', 'level_2'])
print(df_r_2)
#         level_1 level_2  val_1  val_2
# level_3                              
# C0           A0      B0     98     90
# C1           A0      B0     44      9
# C2           A0      B1     39     17
# C3           A0      B1     75     71
# C0           A1      B2      1     89
# C1           A1      B2     54     60
# C2           A1      B3     47      6
# C3           A1      B3     16      5
# C0           A2      B0     75     22
# C1           A2      B0     19      4
# C2           A2      B1     25     52
# C3           A2      B1     57     40
# C0           A3      B2     64     54
# C1           A3      B2     27     96
# C2           A3      B3    100     77
# C3           A3      B3     22     50

マルチインデックスから解除してデータ列からも削除したい場合は引数dropをTrueとします。

df_r_drop = df_m.reset_index(level='level_1', drop=True)
print(df_r_drop)
#                  val_1  val_2
# level_2 level_3              
# B0      C0          98     90
#         C1          44      9
# B1      C2          39     17
#         C3          75     71
# B2      C0           1     89
#         C1          54     60
# B3      C2          47      6
#         C3          16      5
# B0      C0          75     22
#         C1          19      4
# B1      C2          25     52
#         C3          57     40
# B2      C0          64     54
#         C1          27     96
# B3      C2         100     77
#         C3          22     50

例では新たなオブジェクトが返されているが、reset_index()でも引数inplaceをTrueとすると、reset_index()を呼び出したオブジェクト自体が変更される。 reset_index()については以下の記事も参照。

マルチインデックスをソート: sort_index()

マルチインデックスのインデックス列をソートするにはsort_index()を使います。 上の例のようにインデックス列を解除した場合はソートし直したほうが見やすい。 引数をなにも指定しないとレベル順にソートされる。

df_r_drop_sort = df_r_drop.sort_index()
print(df_r_drop_sort)
#                  val_1  val_2
# level_2 level_3              
# B0      C0          98     90
#         C0          75     22
#         C1          44      9
#         C1          19      4
# B1      C2          39     17
#         C2          25     52
#         C3          75     71
#         C3          57     40
# B2      C0           1     89
#         C0          64     54
#         C1          54     60
#         C1          27     96
# B3      C2          47      6
#         C2         100     77
#         C3          16      5
#         C3          22     50

特定のインデックス列を基準にソートしたい場合は、引数levelに列名かレベル値またはそれらのリストを指定します。

df_r_drop_sort_2 = df_r_drop.sort_index(level='level_3')
print(df_r_drop_sort_2)
#                  val_1  val_2
# level_2 level_3              
# B0      C0          98     90
#         C0          75     22
# B2      C0           1     89
#         C0          64     54
# B0      C1          44      9
#         C1          19      4
# B2      C1          54     60
#         C1          27     96
# B1      C2          39     17
#         C2          25     52
# B3      C2          47      6
#         C2         100     77
# B1      C3          75     71
#         C3          57     40
# B3      C3          16      5
#         C3          22     50

sort_index()については以下の記事も参照。

マルチインデックスのレベルを変更: swaplevel()

マルチインデックスのレベル(階層)の順番を変更するにはswaplevel()メソッドを使います。 第一引数と第二引数に列名またはレベル値を指定すると、ふたつのレベル(階層)が交換される。

print(df_m)
#                          val_1  val_2
# level_1 level_2 level_3              
# A0      B0      C0          98     90
#                 C1          44      9
#         B1      C2          39     17
#                 C3          75     71
# A1      B2      C0           1     89
#                 C1          54     60
#         B3      C2          47      6
#                 C3          16      5
# A2      B0      C0          75     22
#                 C1          19      4
#         B1      C2          25     52
#                 C3          57     40
# A3      B2      C0          64     54
#                 C1          27     96
#         B3      C2         100     77
#                 C3          22     50

df_m_swap = df_m.swaplevel('level_1', 'level_3')
print(df_m_swap)
#                          val_1  val_2
# level_3 level_2 level_1              
# C0      B0      A0          98     90
# C1      B0      A0          44      9
# C2      B1      A0          39     17
# C3      B1      A0          75     71
# C0      B2      A1           1     89
# C1      B2      A1          54     60
# C2      B3      A1          47      6
# C3      B3      A1          16      5
# C0      B0      A2          75     22
# C1      B0      A2          19      4
# C2      B1      A2          25     52
# C3      B1      A2          57     40
# C0      B2      A3          64     54
# C1      B2      A3          27     96
# C2      B3      A3         100     77
# C3      B3      A3          22     50

df_m_swap = df_m.swaplevel(0, 2)
print(df_m_swap)
#                          val_1  val_2
# level_3 level_2 level_1              
# C0      B0      A0          98     90
# C1      B0      A0          44      9
# C2      B1      A0          39     17
# C3      B1      A0          75     71
# C0      B2      A1           1     89
# C1      B2      A1          54     60
# C2      B3      A1          47      6
# C3      B3      A1          16      5
# C0      B0      A2          75     22
# C1      B0      A2          19      4
# C2      B1      A2          25     52
# C3      B1      A2          57     40
# C0      B2      A3          64     54
# C1      B2      A3          27     96
# C2      B3      A3         100     77
# C3      B3      A3          22     50

sore_index()でソートすると見やすい。

df_m_swap_sort = df_m.swaplevel('level_1', 'level_3').sort_index()
print(df_m_swap_sort)
#                          val_1  val_2
# level_3 level_2 level_1              
# C0      B0      A0          98     90
#                 A2          75     22
#         B2      A1           1     89
#                 A3          64     54
# C1      B0      A0          44      9
#                 A2          19      4
#         B2      A1          54     60
#                 A3          27     96
# C2      B1      A0          39     17
#                 A2          25     52
#         B3      A1          47      6
#                 A3         100     77
# C3      B1      A0          75     71
#                 A2          57     40
#         B3      A1          16      5
#                 A3          22     50

ふたつのレベルの交換ではなく任意の順番にレベルを変更したい場合は、reset_index()で解除してから再度set_index()で設定すれば問題ありません。

df_m_change = df_m.reset_index().set_index(['level_2', 'level_3', 'level_1']).sort_index()
print(df_m_change)
#                          val_1  val_2
# level_2 level_3 level_1              
# B0      C0      A0          98     90
#                 A2          75     22
#         C1      A0          44      9
#                 A2          19      4
# B1      C2      A0          39     17
#                 A2          25     52
#         C3      A0          75     71
#                 A2          57     40
# B2      C0      A1           1     89
#                 A3          64     54
#         C1      A1          54     60
#                 A3          27     96
# B3      C2      A1          47      6
#                 A3         100     77
#         C3      A1          16      5
#                 A3          22     50

シェア

関連カテゴリー

Python pandas

pandas, Matplotlib(mpl_finance)でローソク足チャートを作成 pandas.DataFrameの行名・列名の変更 pandas.DataFrameをクリップボードにコピーするto_clipboard pandasで時系列データのOHLC(四本値)を算出・ダウンサンプリング pandas.DataFrameから特定の型dtypeの列を抽出(選択) pandasでカテゴリ変数をダミー変数に変換(get_dummies) pandas.DataFrame, SeriesとNumPy配列ndarrayを相互に変換 pandas.DataFrameの行番号、列番号を取得 pandas.DataFrame, Seriesをソートするsort_values, sort_index pandas.DataFrameをJSON文字列・ファイルに変換・保存(to_json) pandasで分位数・パーセンタイルを取得するquantile pandasで条件に応じて値を代入(where, mask) Python, pandasでwebページの表(htmlのtable)をスクレイピング pandasでExcelファイル(xlsx, xls)の書き込み(to_excel) pandasの行・列をランダムサンプリング(抽出)するsample

Last Updated: 6/26/2019, 10:34:03 PM