Pandas マルチインデックス(MultiIndex)
マルチインデックス(MultiIndex)は Pandas の強力なインデックス機能で、行または列に多階層構造を作成できます。これは高次元データ、グループ集計、パネルデータを扱う際に特に役立ちます。
MultiIndex の作成
リストから作成
例
import pandas as pd
# 方法1:配列を使用して作成
arrays = [
["A", "A", "B", "B", "C", "C"],
[1, 2, 1, 2, 1, 2]
]
# pd.MultiIndex.from_arrays を使用
index = pd.MultiIndex.from_arrays(arrays, names=["カテゴリ", "番号"])
print("配列から作成:")
print(index)
print()
# 方法2:タプルリストを使用
tuples = [
("A", 1), ("A", 2), ("B", 1), ("B", 2), ("C", 1), ("C", 2)
]
index = pd.MultiIndex.from_tuples(tuples, names=["カテゴリ", "番号"])
print("タプルから作成:")
print(index)
print()
# 方法3:product を使用
index = pd.MultiIndex.from_product(
[["A", "B", "C"], [1, 2, 3]],
names=["カテゴリ", "番号"]
)
print("product から作成:")
print(index)
# 方法1:配列を使用して作成
arrays = [
["A", "A", "B", "B", "C", "C"],
[1, 2, 1, 2, 1, 2]
]
# pd.MultiIndex.from_arrays を使用
index = pd.MultiIndex.from_arrays(arrays, names=["カテゴリ", "番号"])
print("配列から作成:")
print(index)
print()
# 方法2:タプルリストを使用
tuples = [
("A", 1), ("A", 2), ("B", 1), ("B", 2), ("C", 1), ("C", 2)
]
index = pd.MultiIndex.from_tuples(tuples, names=["カテゴリ", "番号"])
print("タプルから作成:")
print(index)
print()
# 方法3:product を使用
index = pd.MultiIndex.from_product(
[["A", "B", "C"], [1, 2, 3]],
names=["カテゴリ", "番号"]
)
print("product から作成:")
print(index)
MultiIndex 付き DataFrame の作成
例
import pandas as pd
import numpy as np
# マルチインデックス付き DataFrame を作成
df = pd.DataFrame(
np.random.randn(6, 4),
index=pd.MultiIndex.from_tuples(
[("2024", "Q1"), ("2024", "Q2"), ("2024", "Q3"),
("2025", "Q1"), ("2025", "Q2"), ("2025", "Q3")]
),
columns=["北京", "上海", "広州", "深セン"]
)
df.index.names = ["年", "四半期"]
print("マルチインデックス付き DataFrame:")
print(df)
import numpy as np
# マルチインデックス付き DataFrame を作成
df = pd.DataFrame(
np.random.randn(6, 4),
index=pd.MultiIndex.from_tuples(
[("2024", "Q1"), ("2024", "Q2"), ("2024", "Q3"),
("2025", "Q1"), ("2025", "Q2"), ("2025", "Q3")]
),
columns=["北京", "上海", "広州", "深セン"]
)
df.index.names = ["年", "四半期"]
print("マルチインデックス付き DataFrame:")
print(df)
マルチインデックスのアクセス
loc/iloc を使用したアクセス
例
import pandas as pd
# サンプルデータを作成
df = pd.DataFrame({
"国語": [85, 92, 78, 88],
"数学": [90, 88, 95, 82]
}, index=pd.MultiIndex.from_tuples(
[("高1", "A組"), ("高1", "B組"), ("高2", "A組"), ("高2", "B組")],
names=["学年", "クラス"]
))
print("元データ:")
print(df)
print()
# 外側インデックスにアクセス
print("高1のすべてのデータにアクセス:")
print(df.loc["高1"])
print()
# 内側インデックスにアクセス
print("A組にアクセス:")
print(df.loc[:, "A組"])
print()
# マルチインデックスにアクセス
print("高1のA組にアクセス:")
print(df.loc[("高1", "A組")])
# サンプルデータを作成
df = pd.DataFrame({
"国語": [85, 92, 78, 88],
"数学": [90, 88, 95, 82]
}, index=pd.MultiIndex.from_tuples(
[("高1", "A組"), ("高1", "B組"), ("高2", "A組"), ("高2", "B組")],
names=["学年", "クラス"]
))
print("元データ:")
print(df)
print()
# 外側インデックスにアクセス
print("高1のすべてのデータにアクセス:")
print(df.loc["高1"])
print()
# 内側インデックスにアクセス
print("A組にアクセス:")
print(df.loc[:, "A組"])
print()
# マルチインデックスにアクセス
print("高1のA組にアクセス:")
print(df.loc[("高1", "A組")])
xs を使用したアクセス
例
import pandas as pd
# サンプルデータを作成
df = pd.DataFrame({
"国語": [85, 92, 78, 88],
"数学": [90, 88, 95, 82]
}, index=pd.MultiIndex.from_tuples(
[("高1", "A組"), ("高1", "B組"), ("高2", "A組"), ("高2", "B組")],
names=["学年", "クラス"]
))
# xs を使用して特定レベルの値にアクセス
print("xs を使用して高1のデータにアクセス:")
print(df.xs("高1", level="学年"))
print()
print("xs を使用してA組にアクセス:")
print(df.xs("A組", level="クラス"))
# サンプルデータを作成
df = pd.DataFrame({
"国語": [85, 92, 78, 88],
"数学": [90, 88, 95, 82]
}, index=pd.MultiIndex.from_tuples(
[("高1", "A組"), ("高1", "B組"), ("高2", "A組"), ("高2", "B組")],
names=["学年", "クラス"]
))
# xs を使用して特定レベルの値にアクセス
print("xs を使用して高1のデータにアクセス:")
print(df.xs("高1", level="学年"))
print()
print("xs を使用してA組にアクセス:")
print(df.xs("A組", level="クラス"))
マルチインデックスの変換
スタックとアンスタック
例
import pandas as pd
import numpy as np
# ワイド形式の DataFrame を作成
df = pd.DataFrame(
np.arange(12).reshape(3, 4),
index=pd.MultiIndex.from_tuples(
[("北京", "2024"), ("上海", "2024"), ("広州", "2024")]
),
columns=pd.MultiIndex.from_tuples(
[("Q1", "売上"), ("Q1", "利益"), ("Q2", "売上"), ("Q2", "利益")]
)
)
print("元データ(ネストされた列):")
print(df)
print()
# unstack:内側インデックスを列に変換
df_unstacked = df.unstack()
print("unstack 後:")
print(df_unstacked)
print()
# stack:列を内側インデックスに変換
df_stacked = df_unstacked.stack()
print("stack 後:")
print(df_stacked)
import numpy as np
# ワイド形式の DataFrame を作成
df = pd.DataFrame(
np.arange(12).reshape(3, 4),
index=pd.MultiIndex.from_tuples(
[("北京", "2024"), ("上海", "2024"), ("広州", "2024")]
),
columns=pd.MultiIndex.from_tuples(
[("Q1", "売上"), ("Q1", "利益"), ("Q2", "売上"), ("Q2", "利益")]
)
)
print("元データ(ネストされた列):")
print(df)
print()
# unstack:内側インデックスを列に変換
df_unstacked = df.unstack()
print("unstack 後:")
print(df_unstacked)
print()
# stack:列を内側インデックスに変換
df_stacked = df_unstacked.stack()
print("stack 後:")
print(df_stacked)
マルチインデックスのソート
例
import pandas as pd
# 順序が乱れたインデックスを持つ DataFrame を作成
df = pd.DataFrame({
"値": [1, 2, 3, 4, 5, 6]
}, index=pd.MultiIndex.from_tuples(
[("C", 2), ("A", 1), ("B", 2), ("A", 2), ("C", 1), ("B", 1)],
names=["アルファベット", "数字"]
))
print("順不同のデータ:")
print(df)
print()
# 外側でソート
df_sorted1 = df.sort_index()
print("外側でソート後:")
print(df_sorted1)
print()
# 内側でソート
df_sorted2 = df.sort_index(level=1)
print("内側でソート後:")
print(df_sorted2)
print()
# マルチレベルでソート
df_sorted3 = df.sort_index(level=[0, 1])
print("マルチレベルでソート後:")
print(df_sorted3)
# 順序が乱れたインデックスを持つ DataFrame を作成
df = pd.DataFrame({
"値": [1, 2, 3, 4, 5, 6]
}, index=pd.MultiIndex.from_tuples(
[("C", 2), ("A", 1), ("B", 2), ("A", 2), ("C", 1), ("B", 1)],
names=["アルファベット", "数字"]
))
print("順不同のデータ:")
print(df)
print()
# 外側でソート
df_sorted1 = df.sort_index()
print("外側でソート後:")
print(df_sorted1)
print()
# 内側でソート
df_sorted2 = df.sort_index(level=1)
print("内側でソート後:")
print(df_sorted2)
print()
# マルチレベルでソート
df_sorted3 = df.sort_index(level=[0, 1])
print("マルチレベルでソート後:")
print(df_sorted3)
実践:グループ集計
マルチインデックスはグループ集計やピボット分析に非常に適しています。
例
import pandas as pd
import numpy as np
# 売上データを作成
np.random.seed(42)
df = pd.DataFrame({
"年": ["2023"] * 6 + ["2024"] * 6,
"四半期": ["Q1", "Q2", "Q3", "Q4"] * 3,
"製品": ["スマートフォン", "スマートフォン", "パソコン", "パソコン"] * 3,
"地域": ["華東", "華南", "華北"] * 4,
"売上高": np.random.randint(100, 500, 12)
})
print("元の売上データ:")
print(df)
print()
# マルチインデックスを設定してからグループ集計を行う
df_grouped = df.set_index(["年", "四半期", "製品", "地域"])
print("年、四半期、製品、地域でグループ化:")
print(df_grouped)
# 年ごとに集計
yearly = df_grouped.groupby(level="年").sum()
print("\n年間売上高:")
print(yearly)
# 年と四半期ごとに集計
quarterly = df_grouped.groupby(level=["年", "四半期"]).sum()
print("\n四半期売上高:")
print(quarterly)
import numpy as np
# 売上データを作成
np.random.seed(42)
df = pd.DataFrame({
"年": ["2023"] * 6 + ["2024"] * 6,
"四半期": ["Q1", "Q2", "Q3", "Q4"] * 3,
"製品": ["スマートフォン", "スマートフォン", "パソコン", "パソコン"] * 3,
"地域": ["華東", "華南", "華北"] * 4,
"売上高": np.random.randint(100, 500, 12)
})
print("元の売上データ:")
print(df)
print()
# マルチインデックスを設定してからグループ集計を行う
df_grouped = df.set_index(["年", "四半期", "製品", "地域"])
print("年、四半期、製品、地域でグループ化:")
print(df_grouped)
# 年ごとに集計
yearly = df_grouped.groupby(level="年").sum()
print("\n年間売上高:")
print(yearly)
# 年と四半期ごとに集計
quarterly = df_grouped.groupby(level=["年", "四半期"]).sum()
print("\n四半期売上高:")
print(quarterly)
よくある質問と注意点
1. インデックス階層の混乱
データ操作時は、階層の混乱を避けるために注意してください。操作の前後で確認することをお勧めします。df.index.names。
2. インデックスアクセスのエラー
loc"ラベルを使用したアクセス、"iloc"位置を使用したアクセス。この2つを混用しないでください。"
3. concat 時のインデックス重複
使用concatデータを結合する際、重複インデックスがあると予期しない結果を招く可能性があります。ignore_index=Trueリセットしてください。
その他の拡張マルチインデックスは Pandas で高次元データを扱うための核となる機能です。マルチインデックスを適切に使用することで、データの整理がより明確になり、集計がより便利になります。