【Pandas上級】MultiIndexの操作完全ガイド:指定・追加・解除・ソート・レベル変更


 

PandasのMultiIndex(マルチインデックス)は、DataFrameやSeriesに複数の階層を持つインデックスを設定できる強力な機能です。これにより、より複雑なデータ構造を効率的に表現し、詳細なグループ化や集計が可能になります。しかし、その強力さゆえに、MultiIndexの操作は通常のインデックスよりも少し複雑に感じられるかもしれません。

この記事では、MultiIndexの指定(作成)から、既存のDataFrameへの追加、不要になったインデックスの解除、階層順のソート、そしてインデックスレベルの変更まで、MultiIndexを自在に操るための主要なテクニックを、短いサンプルコードと丁寧な解説を交えてご紹介します。


 

MultiIndexとは?なぜ高度なインデックスが必要なのか?

 

MultiIndexは、DataFrameの行または列、あるいはその両方に、複数のレベル(階層)を持つインデックスを設定する機能です。これにより、カテゴリ間の親子関係や、複数軸でのデータ分類を表現できます。

MultiIndexがデータ分析において重要な理由は以下の通りです。

  • 多次元データの表現: リレーショナルデータベースの複合主キーのように、複数の情報(例: 地域、年、月)を組み合わせてデータを一意に識別したい場合に役立ちます。

  • 階層的なデータ集計: groupby()などで複数の列をグループ化すると、結果としてMultiIndexが生成されることが多く、その後の分析をスムーズに進めるために操作方法の理解が不可欠です。

  • データの整理と分析: 複雑なデータでも、階層的なインデックスによって整理され、特定のサブグループへのアクセスが直感的になります。


 

1. MultiIndexの指定(作成)とDataFrameへの適用

 

MultiIndexを作成する方法はいくつかありますが、最も一般的なのはpd.MultiIndex.from_product()を使う方法と、既存のDataFrameからset_index()を使う方法です。

 

pd.MultiIndex.from_product()で直接作成

 

複数のリストのデカルト積(すべての組み合わせ)からMultiIndexを生成します。

Python
 
import pandas as pd
import numpy as np

# MultiIndexを直接作成
idx = pd.MultiIndex.from_product([['東京', '大阪'], ['2023', '2024']], names=['地域', '年'])
print("作成したMultiIndex:\n", idx)

# MultiIndexを持つDataFrameを作成
df_multi_create = pd.DataFrame(
    np.random.randint(100, 500, (4, 2)), # 4行2列のランダムなデータ
    index=idx,
    columns=['売上', '費用']
)
print("\nMultiIndexを持つDataFrame:\n", df_multi_create)

解説:

pd.MultiIndex.from_product()にリストのリスト(各レベルの要素)を渡し、namesで各レベルの名前を指定します。これにより、すべての組み合わせが網羅された階層的なインデックスが作成されます。


 

2. MultiIndexの追加(既存列から設定)

 

既存のDataFrameの1つ以上の列をインデックスに設定してMultiIndexを作成するには、set_index()メソッドを使用します。これはデータロード後によく使われる方法です。

Python
 
# サンプルDataFrame
df_add_multi = pd.DataFrame({
    '都市': ['東京', '東京', '大阪', '大阪'],
    '月': ['1月', '2月', '1月', '2月'],
    '売上': [100, 120, 150, 130]
})
print("オリジナルDataFrame:\n", df_add_multi)

# '都市'と'月'をMultiIndexに設定
df_added_multi = df_add_multi.set_index(['都市', '月'])
print("\n'都市'と'月'をMultiIndexに設定後:\n", df_added_multi)

解説:

set_index()に列名のリストを渡すだけで、それらの列が新しいMultiIndexのレベルとして設定されます。元の列はデフォルトでDataFrameから削除されます。


 

3. MultiIndexの解除

 

MultiIndexを通常の列に戻したり、デフォルトの連番インデックスに戻したりするには、reset_index()メソッドを使用します。

 

全てのレベルを解除する

 

MultiIndexの全てのレベルを列に戻し、デフォルトの連番インデックスを割り当てます。

Python
 
# 先ほど作成したMultiIndex DataFrameを使用
df_reset_all = df_added_multi.reset_index()
print("\n全てのMultiIndexレベルを解除後:\n", df_reset_all)

解説:

reset_index()を引数なしで呼び出すと、全てのインデックスレベルがDataFrameの新しい列として追加され、インデックスは0, 1, 2…にリセットされます。

 

特定のレベルのみを解除する

 

level引数を使うと、MultiIndexの特定のレベルだけを解除して列に戻すことができます。

Python
 
# '月'レベルのみを解除
df_reset_level = df_added_multi.reset_index(level='月')
print("\n'月'レベルのみ解除後:\n", df_reset_level)

解説:

level=’月’と指定したことで、’月’レベルのみが列に戻り、’都市’レベルは引き続きインデックスとして残っています。


 

4. MultiIndexのソート

 

MultiIndexは、その階層構造を意識してソートする必要があります。sort_index()メソッドを使用します。

 

インデックス全体をソートする

 

デフォルトでは、sort_index()はMultiIndexの全てのレベルを左から右へ順にソートします。

Python
 
# ソートするために順序を入れ替えたDataFrameを作成
df_sort_example = pd.DataFrame({
    'Value': [10, 20, 30, 40]
}, index=pd.MultiIndex.from_product([['B', 'A'], [2, 1]], names=['レベル1', 'レベル2']))
print("ソート前MultiIndex DataFrame:\n", df_sort_example)

# インデックス全体をソート
df_sorted_multi = df_sort_example.sort_index()
print("\nインデックス全体をソート後:\n", df_sorted_multi)

解説:

まず’レベル1’がソートされ、次に同じ’レベル1’の中では’レベル2’がソートされます。

 

特定のレベルを指定してソートする

 

level引数を使うと、特定のレベルだけを基準にソートすることができます。

Python
 
# 'レベル2'だけを基準にソート
df_sorted_level = df_sort_example.sort_index(level='レベル2')
print("\n'レベル2'だけを基準にソート後:\n", df_sorted_level)

解説:

この場合、’レベル2’の値に基づいてまずソートされ、その後で’レベル1’がソートされます。


 

5. MultiIndexのレベル変更

 

MultiIndexのレベルの順序を変更したり、レベル名を変更したりすることができます。

 

レベルの順序を変更する: swaplevel()

 

MultiIndexの2つのレベルの順序を入れ替えます。

Python
 
# '地域'と'月'の順序を入れ替える
df_swapped_level = df_added_multi.swaplevel('地域', '月')
print("\nレベル順序入れ替え後:\n", df_swapped_level)

# 入れ替えた後にソートすると、新しい順序で整列される
df_swapped_level_sorted = df_swapped_level.sort_index()
print("\nレベル入れ替え後ソート済み:\n", df_swapped_level_sorted)

解説:

swaplevel()はインデックスの順序を変更するだけで、ソートは自動で行われないため、必要に応じてsort_index()を適用することが多いです。

 

レベル名を変更する: rename()またはset_names()

 

MultiIndexのレベルの名前を変更します。

Python
 
# rename()でレベル名を変更
df_renamed_level = df_added_multi.rename(index={'地域': 'Prefecture', '月': 'Month'})
print("\nレベル名変更後 (rename):\n", df_renamed_level)

# set_names()でレベル名を変更 (MultiIndexオブジェクトに直接適用)
df_set_names = df_added_multi.copy()
df_set_names.index.set_names(['Location', 'Period'], inplace=True)
print("\nレベル名変更後 (set_names):\n", df_set_names)

解説:

  • rename(index=...): DataFrameのメソッドで、インデックスのマップ(辞書)を渡して名前を変更します。

  • df.index.set_names(): MultiIndexオブジェクト自体に対して直接メソッドを呼び出し、リストで新しい名前を指定します。inplace=Trueで元のオブジェクトを変更します。


 

まとめ

 

PandasのMultiIndexは、複雑なデータ構造を効率的に表現し、より高度なデータ分析を可能にする強力な機能です。MultiIndexの指定(from_product(), set_index()解除(reset_index()ソート(sort_index()、そして**レベル変更(swaplevel(), rename(), set_names())**といった一連の操作をマスターすることで、データの整形から分析まで、あなたのPandasスキルは飛躍的に向上するでしょう。これらのテクニックを使いこなし、階層的なデータを自在に操りましょう。