Pandas unstack 徹底解説: 多重インデックスを列に展開してデータを再構築!
Pandasでデータ分析を行う際、多層的なカテゴリを持つデータを扱うことは珍しくありません。このようなデータは、しばしば多重インデックス (MultiIndex) を持つDataFrameとして表現されます。しかし、時にはこれらの階層的なインデックスを列として展開し、データをよりワイドな形式に変換したい場合があります。そんな時に強力な味方となるのが、Pandasの**unstack**メソッドです。
この記事では、Pandas unstackの基本的な使い方から、多重インデックスを効率的に操作し、データを再構築するための応用テクニックまで、徹底的に解説します。
Pandas unstackってどんなもの?
Pandasのunstackメソッドは、DataFrame(またはSeries)のMultiIndex(多重インデックス)のレベルを、新しい列(カラム)として「展開(unstack)」するための機能です。これは、pivotと似たような変換を行いますが、unstackは特にMultiIndexの内部構造を操作することに特化しています。
unstackでできること
多重インデックスの列展開: 行インデックスの一部または全体を新しい列として展開し、データをワイド形式に変換します。
データの再整形: 統計分析や特定の可視化ツールが求めるデータ形式に変換します。
グループ化結果の整形:
groupby()で集計した結果がMultiIndexになっている場合、その結果を見やすいワイド形式に整形します。
なぜunstackを選ぶべきか?
データ整形の手法は他にもありますが、unstackを使うことには以下のようなメリットがあります。
MultiIndexとの親和性: 多重インデックスを持つデータに対して、直感的かつ効率的にデータの形状を変更できます。
簡潔なコード: 複雑なループや条件分岐なしに、数行のコードでデータの再構築が可能です。
高速性: Pandasの内部最適化により、大量のデータでも効率的に処理できます。
データの可視化や分析準備: ワイド形式にすることで、クロス集計表を作成したり、特定の可視化ライブラリへの入力を準備したりするのに役立ちます。
unstackを始めるための準備
1. ライブラリのインポートとデータの準備
unstackを使うためには、Pandasライブラリをインポートし、操作したいデータがMultiIndexを持つDataFrameまたはSeriesとして用意されている必要があります。
import pandas as pd
import numpy as np
# サンプルデータフレームの作成 (MultiIndexを持つロング形式)
# 各地域、各年の売上データと顧客数が縦に並んでいる想定
data = {
'Region': ['East', 'East', 'East', 'West', 'West', 'West', 'East', 'West'],
'Year': [2022, 2023, 2024, 2022, 2023, 2024, 2023, 2022],
'Sales': [100, 110, 120, 150, 160, 170, 90, 140],
'Customers': [20, 22, 25, 30, 32, 35, 18, 28]
}
df = pd.DataFrame(data)
# 'Region'と'Year'をインデックスに設定 (MultiIndexを作成)
# 複数の値列があるので、一旦groupbyで集計してMultiIndexを作成するのが一般的
df_indexed = df.groupby(['Region', 'Year']).agg({'Sales': 'sum', 'Customers': 'sum'})
print("--- 元のデータフレーム (MultiIndexを持つ) ---")
print(df_indexed)
print("\n")
unstackの基本的な使い方
unstackメソッドは、どのインデックスレベルを列として展開するかをlevel引数で指定します。デフォルトでは、最も内側のレベルが展開されます。
最小限のサンプルプログラム
例1: 最も内側のインデックスレベル (‘Year’) を列に展開
df_indexedはRegionとYearの多重インデックスを持っています。unstackを引数なしで呼び出すと、最も内側のレベルであるYearが列として展開されます。
# 'Year'レベルを列に展開
df_unstacked_year = df_indexed.unstack()
print("--- 'Year'を列に展開した結果 ---")
print(df_unstacked_year)
print("\n")
この結果、SalesとCustomersという元の列がそれぞれ多階層カラムとして残り、その中に各年の値がネストされたワイド形式のDataFrameが生成されます。
例2: 特定のインデックスレベル (‘Region’) を列に展開
level引数に展開したいインデックスレベルの名前(または数値)を指定します。
# 'Region'レベルを列に展開
df_unstacked_region = df_indexed.unstack(level='Region')
print("--- 'Region'を列に展開した結果 ---")
print(df_unstacked_region)
print("\n")
この場合、Yearが単一の行インデックスとして残り、SalesとCustomersという元の列の下にRegionが多階層カラムとして展開されます。
unstackの応用テクニック
1. Seriesに対するunstack
unstackはSeriesに対しても適用でき、SeriesのMultiIndexをDataFrameに変換します。
# Seriesでのunstack例
s_multi = pd.Series([10, 20, 30, 40], index=[['A', 'A', 'B', 'B'], [1, 2, 1, 2]])
print("--- 元のMultiIndex Series ---")
print(s_multi)
print("\n")
s_unstacked = s_multi.unstack()
print("--- Seriesをunstackした結果 ---")
print(s_unstacked)
print("\n")
2. fill_valueで欠損値を埋める
unstackの結果、データが存在しない組み合わせにはNaN(欠損値)が表示されます。これを特定の値で埋めるにはfill_value引数を使います。
# 例: 意図的に欠損値が発生するMultiIndexデータ
data_sparse = {
'Category': ['X', 'X', 'Y'],
'SubCategory': ['a', 'b', 'a'],
'Value': [1, 2, 3]
}
df_sparse = pd.DataFrame(data_sparse).set_index(['Category', 'SubCategory'])
print("--- 欠損値を含む元データ ---")
print(df_sparse)
print("\n")
# unstackし、NaNを0で埋める
df_unstacked_filled = df_sparse.unstack(fill_value=0)
print("--- unstackし、NaNを0で埋めた結果 ---")
print(df_unstacked_filled)
print("\n")
3. 複数のレベルを一度に展開(または積み重ねる)
unstackは一度に1つのレベルしか展開できませんが、複数のunstackをチェーンしたり、stackと組み合わせて複雑な変換を行うことができます。
unstackとpivot、pivot_table、meltの使い分け
Pandasにはデータの形状を変換する複数の強力な関数があり、それぞれ最適な利用シーンがあります。
unstack():MultiIndexを持つDataFrame/Seriesの行インデックスのレベルを列に展開したい場合に特化。
集計機能はなく、単にデータの形状を再構築します。
pivotと異なり、元のデータに重複するインデックスの組み合わせがあっても、それを列に展開するだけでエラーにはなりません(ただし、values列がない場合)。
pivot():特定の列を
index、別の列をcolumnsに、さらに別の列をvaluesにしてデータをワイド形式に再構築したい場合。indexとcolumnsの組み合わせが一意である必要がある(重複するとエラー)。集計機能はない。
pivot_table():pivotと同様にデータをワイド形式に再構築するが、同時に集計機能を持つ。indexとcolumnsの組み合わせが重複しても集計してくれるためエラーにならない。最も柔軟なクロス集計ツール。
melt():ワイド形式のデータをロング形式に変換する(
unstackやpivotの逆操作)。複数の「測定値の列」を「変数名」と「値」の2つの列に「溶解」する。
簡単な使い分けの例:
unstack:df.groupby(['A', 'B'])['Value'].sum().unstack('B')のように、groupby結果のMultiIndexを列にしたい。pivot: 「日付」「商品」「売上」のロング形式から、「日付」を行、「商品」を列、売上を値とする表にしたい(日付・商品の組み合わせはユニーク)。pivot_table: 「日付」「商品」「売上」で、同じ日付・商品の売上が複数ある場合に、「日付」を行、「商品」を列、売上合計を値とする表にしたい。melt: 「年ごとの売上列(Year_2022, Year_2023…)」が並んだワイド形式のデータから、「年」「売上」というロング形式に変換したい。
まとめ
この記事では、Pandasで多重インデックスを持つDataFrame/Seriesを効率的にワイド形式に変換する**unstack**メソッドについて、その特徴、基本的な使い方、そしてpivotやpivot_table、meltとの違いや使い分けを徹底的に解説しました。
unstackを適切に活用することで、多層的なカテゴリを持つデータの分析や可視化の準備を、簡潔かつ効率的に行えるようになります。特に、groupby()による集計結果をより見やすいクロス集計表のような形にしたい場合に、unstackは強力な味方となるでしょう。
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座

