Pandas df.unstack() 関数
df.unstack()DataFrame のメンバーメソッドであり、次の用途に使用します行インデックスを列インデックスに変換します。階層化インデックスを持つデータを「展開」し、行レベルの1つ以上の階層を列に移動します。
これはデータ再形成の重要な操作であり、通常はstack()と組み合わせて使用し、データの相互変換を実現します。
単語の意味: unstackは「分解して展開する」という意味で、ここでは行インデックスを列に「展開」し、縦長テーブルを横長テーブルに変換することを指します。
基本構文とパラメータ
df.unstack()は DataFrame のインスタンスメソッドで、ドット演算子で呼び出します。
構文形式
DataFrame.unstack(level=-1, fill_value=None)
パラメータの説明
- パラメータ:
level- 型: int、str、int のリスト、または str のリスト。
- 説明: 列に展開する階層を指定します。マルチレベルインデックスの場合、具体的な階層番号(0始まり)または階層名を指定できます。デフォルトは -1 で、最内層を表します。
- パラメータ:
fill_value- 型: スカラーまたは None。
- 説明: unstack 操作によって生成された欠損値を埋めるための値です。デフォルトは None で、NaN を保持します。
関数の説明
- 戻り値: Series または DataFrame を返します。元の DataFrame で展開される行階層が1つのみの場合は Series を返し、それ以外の場合は DataFrame を返します。
- 効果: 行インデックスの1つ以上の階層を列インデックスに移動し、より横長のデータ形式を生成します。展開後のデータは「横長形式」になり、表示や比較が容易です。
実例
簡単なものから複雑なものまでの一連の例を通して、徹底的にdf.unstack()の使い方を習得しましょう。
例1:基本用法 - 行を列に変換する
実例
import pandas as pd
# 1. 縦長形式データを作成
df = pd.DataFrame({
'product': ['A', 'A', 'B', 'B', 'C', 'C'],
'region': ['North', 'South', 'North', 'South', 'North', 'South'],
'sales': [100, 150, 200, 180, 220, 250]
})
print("=== 元の縦長形式データ ===")
print(df)
# 2. 階層化インデックスを設定
df_indexed = df.set_index(['product', 'region'])
print("n=== 階層化インデックス設定後 ===")
print(df_indexed)
# 3. df.unstack() を使用して内側インデックスを列に変換
unstacked = df_indexed.unstack()
print("n=== df.unstack() 結果 ===")
print(unstacked)
# 4. 表示を簡略化
print("n=== 売上のみ表示 ===")
print(unstacked['sales'])
# 1. 縦長形式データを作成
df = pd.DataFrame({
'product': ['A', 'A', 'B', 'B', 'C', 'C'],
'region': ['North', 'South', 'North', 'South', 'North', 'South'],
'sales': [100, 150, 200, 180, 220, 250]
})
print("=== 元の縦長形式データ ===")
print(df)
# 2. 階層化インデックスを設定
df_indexed = df.set_index(['product', 'region'])
print("n=== 階層化インデックス設定後 ===")
print(df_indexed)
# 3. df.unstack() を使用して内側インデックスを列に変換
unstacked = df_indexed.unstack()
print("n=== df.unstack() 結果 ===")
print(unstacked)
# 4. 表示を簡略化
print("n=== 売上のみ表示 ===")
print(unstacked['sales'])
実行結果の期待値:
=== 原始长格式数据 ===
product region sales
0 A North 100
1 A South 150
2 B North 200
3 B South 180
4 C North 220
5 C South 250
n=== 设置层次化索引后 ===
sales
product region
A North 100
South 150
B North 200
South 180
C North 220
South 250
n=== df.unstack() 结果 ===
sales
region North South
product
A 100 150
B 200 180
C 220 250
n=== 只看销售额 ===
region North South
product
A 100 150
B 200 180
C 220 250
コードの解説:
- 元のデータは縦長形式で、各行に各製品の各地区での売上が記録されています。
- set_index を
set_index()使用して階層化インデックスを作成します(product が外側、region が内側)。 unstack()内側インデックス region を列の位置に移動します。- 結果は横長形式になり、さまざまな製品の各地区での販売データを直感的に比較できます。
例2:マルチレベルインデックスの展開
DataFrame に複数の行インデックス階層がある場合、展開する階層を指定できます。
実例
import pandas as pd
# 1. 複数の行インデックスを持つデータを作成
df = pd.DataFrame({
'year': [2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024],
'quarter': ['Q1', 'Q1', 'Q2', 'Q2', 'Q1', 'Q1', 'Q2', 'Q2'],
'product': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
'sales': [100, 150, 200, 180, 220, 250, 230, 270]
})
print("=== 元のデータ ===")
print(df)
# 2. 複数階層インデックスを設定
df_indexed = df.set_index(['year', 'quarter', 'product'])
print("n=== 複数階層インデックスの設定 ===")
print(df_indexed)
# 3. 最内層を展開(product、デフォルト level=-1)
print("n=== product 階層の展開(デフォルト)===")
unstacked_inner = df_indexed.unstack()
print(unstacked_inner['sales'])
# 4. 中間層を展開(quarter)
print("n=== quarter 階層の展開 ===")
unstacked_quarter = df_indexed.unstack(level='quarter')
print(unstacked_quarter['sales'])
# 5. 外側の階層を展開(year)
print("n=== year 階層の展開 ===")
unstacked_year = df_indexed.unstack(level='year')
print(unstacked_year['sales'])
# 6. 複数の階層を同時に展開
print("n=== year と product の同時展開 ===")
unstacked_multi = df_indexed.unstack(level=['year', 'product'])
print(unstacked_multi['sales'])
# 1. 複数の行インデックスを持つデータを作成
df = pd.DataFrame({
'year': [2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024],
'quarter': ['Q1', 'Q1', 'Q2', 'Q2', 'Q1', 'Q1', 'Q2', 'Q2'],
'product': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
'sales': [100, 150, 200, 180, 220, 250, 230, 270]
})
print("=== 元のデータ ===")
print(df)
# 2. 複数階層インデックスを設定
df_indexed = df.set_index(['year', 'quarter', 'product'])
print("n=== 複数階層インデックスの設定 ===")
print(df_indexed)
# 3. 最内層を展開(product、デフォルト level=-1)
print("n=== product 階層の展開(デフォルト)===")
unstacked_inner = df_indexed.unstack()
print(unstacked_inner['sales'])
# 4. 中間層を展開(quarter)
print("n=== quarter 階層の展開 ===")
unstacked_quarter = df_indexed.unstack(level='quarter')
print(unstacked_quarter['sales'])
# 5. 外側の階層を展開(year)
print("n=== year 階層の展開 ===")
unstacked_year = df_indexed.unstack(level='year')
print(unstacked_year['sales'])
# 6. 複数の階層を同時に展開
print("n=== year と product の同時展開 ===")
unstacked_multi = df_indexed.unstack(level=['year', 'product'])
print(unstacked_multi['sales'])
実行結果の期待値:
=== 原始数据 ===
year quarter product sales
0 2023 Q1 A 100
1 2023 Q1 B 150
2 2023 Q2 A 200
3 2023 Q2 B 180
4 2024 Q1 A 220
5 2024 Q1 B 250
6 2024 Q2 A 230
7 2024 Q2 B 270
n=== 设置多层索引 ===
sales
year quarter product
2023 Q1 A 100
B 150
Q2 A 200
B 180
2024 Q1 A 220
B 250
Q2 A 230
B 270
n=== 展开 product 层(默认)===
product A B
year quarter
2023 Q1 100 150
Q2 200 180
2024 Q1 220 250
Q2 230 270
n=== 展开 quarter 层 ===
quarter Q1 Q2
year product
2023 A 100 200
B 150 180
2024 A 220 230
B 250 270
n=== 展开 year 层 ===
year 2023 2024
quarter product
Q1 A 100 220
B 150 250
Q2 A 200 230
B 180 270
n=== 同时展开 year 和 product ===
year 2023 2024
product A B A B
quarter
Q1 100 150 220 250
Q2 200 180 230 270
コードの解説:
- マルチレベルインデックスの DataFrame では、level パラメータを
level使用して、展開する階層を指定できます。 - デフォルトでは
level=-1最内層(product)を展開します。 - 異なる階層を展開すると異なるデータ配置が生成され、さまざまな角度からデータを分析しやすくなります。
例3:fill_value を使用した欠損値の処理
fill_value パラメータをfill_value使用すると、unstack 後に生成される欠損値を埋められます。
実例
import pandas as pd
import numpy as np
# 1. 不完全なデータを作成(すべての製品-地区の組み合わせにデータがあるわけではない)
df = pd.DataFrame({
'product': ['A', 'A', 'B', 'C'],
'region': ['North', 'South', 'North', 'East'],
'sales': [100, 150, 200, 220]
})
print("=== 元のデータ(不完全)===")
print(df)
# 2. 階層化インデックスを作成して unstack
df_indexed = df.set_index(['product', 'region'])
print("n=== 階層化インデックス ===")
print(df_indexed)
# 3. 欠損値を埋めない
print("n=== 欠損値を埋めない ===")
unstacked = df_indexed.unstack()
print(unstacked)
print(f"欠損値の数: {unstacked['sales'].isna().sum().sum()}")
# 4. fill_value=0 を使用して欠損値を埋める
print("n=== fill_value=0 ===")
unstacked_fill = df_indexed.unstack(fill_value=0)
print(unstacked_fill)
print(f"欠損値の数: {unstacked_fill['sales'].isna().sum().sum()}")
import numpy as np
# 1. 不完全なデータを作成(すべての製品-地区の組み合わせにデータがあるわけではない)
df = pd.DataFrame({
'product': ['A', 'A', 'B', 'C'],
'region': ['North', 'South', 'North', 'East'],
'sales': [100, 150, 200, 220]
})
print("=== 元のデータ(不完全)===")
print(df)
# 2. 階層化インデックスを作成して unstack
df_indexed = df.set_index(['product', 'region'])
print("n=== 階層化インデックス ===")
print(df_indexed)
# 3. 欠損値を埋めない
print("n=== 欠損値を埋めない ===")
unstacked = df_indexed.unstack()
print(unstacked)
print(f"欠損値の数: {unstacked['sales'].isna().sum().sum()}")
# 4. fill_value=0 を使用して欠損値を埋める
print("n=== fill_value=0 ===")
unstacked_fill = df_indexed.unstack(fill_value=0)
print(unstacked_fill)
print(f"欠損値の数: {unstacked_fill['sales'].isna().sum().sum()}")
実行結果の期待値:
=== 原始数据(不完整)===
product region sales
0 A North 100
1 A South 150
2 B North 200
3 C East 220
n=== 层次化索引 ===
sales
product region
A North 100
South 150
B North 200
C East 220
n=== 不填充缺失值 ===
sales
region East North South
product
A NaN 100.0 150.0
B NaN 200.0 NaN
C 220.0 NaN NaN
缺失值数量: 5
n=== fill_value=0 ===
sales
region East North South
product
A 0 100 150
B 0 200 0
C 220 0 0
缺失值数量: 0
コードの解説:
- 元のデータが不完全な場合、unstack は欠損値(NaN)を生成します。
- fill_value パラメータを
fill_value使用すると、埋め合わせ値を指定でき、後続の計算エラーを防げます。 - 通常は 0 を埋めて「データなし」または「その組み合わせが存在しない」ことを示します。
例4:unstack と stack の組み合わせ使用
unstack()とstack()は互いに逆の操作であり、組み合わせて使用することでデータを柔軟に再形成できます。
実例
import pandas as pd
# 1. 初期の横長形式データを作成
df = pd.DataFrame({
'product': ['A', 'B', 'C'],
'North': [100, 150, 200],
'South': [180, 170, 160],
'East': [190, 200, 210]
})
print("=== 元の横長形式データ ===")
print(df)
# 2. 最初に stack で縦長形式に変換
print("n=== step 1: stack で縦長形式に変換 ===")
stacked = df.set_index('product').stack()
print(stacked)
# 3. 次に unstack で元に戻す(可逆性の検証)
print("n=== step 2: unstack で横長形式に戻す ===")
restored = stacked.unstack()
print(restored)
# 4. 実践:データを並べ替える
print("n=== 実践:region を列に移動 ===")
# 元:product が行インデックス、region が列
# 目標:region が行インデックス、product が列
result = df.set_index('product').unstack().unstack(level=-1)
print(result)
# 5. reorder_levels を使用して階層の順序を調整
print("n=== reorder_levels による階層の調整 ===")
# 2階層インデックスを作成
df_multi = pd.DataFrame(
[[100, 200], [150, 180], [190, 210]],
index=pd.MultiIndex.from_tuples([
('A', 'North'), ('B', 'North'), ('C', 'North')
], names=['product', 'region']),
columns=['2023', '2024']
)
print("元のデータ:")
print(df_multi)
# 階層の順序を調整
print("n調整後(年が外側):")
print(df_multi.unstack(level='region'))
# 1. 初期の横長形式データを作成
df = pd.DataFrame({
'product': ['A', 'B', 'C'],
'North': [100, 150, 200],
'South': [180, 170, 160],
'East': [190, 200, 210]
})
print("=== 元の横長形式データ ===")
print(df)
# 2. 最初に stack で縦長形式に変換
print("n=== step 1: stack で縦長形式に変換 ===")
stacked = df.set_index('product').stack()
print(stacked)
# 3. 次に unstack で元に戻す(可逆性の検証)
print("n=== step 2: unstack で横長形式に戻す ===")
restored = stacked.unstack()
print(restored)
# 4. 実践:データを並べ替える
print("n=== 実践:region を列に移動 ===")
# 元:product が行インデックス、region が列
# 目標:region が行インデックス、product が列
result = df.set_index('product').unstack().unstack(level=-1)
print(result)
# 5. reorder_levels を使用して階層の順序を調整
print("n=== reorder_levels による階層の調整 ===")
# 2階層インデックスを作成
df_multi = pd.DataFrame(
[[100, 200], [150, 180], [190, 210]],
index=pd.MultiIndex.from_tuples([
('A', 'North'), ('B', 'North'), ('C', 'North')
], names=['product', 'region']),
columns=['2023', '2024']
)
print("元のデータ:")
print(df_multi)
# 階層の順序を調整
print("n調整後(年が外側):")
print(df_multi.unstack(level='region'))
実行結果の期待値:
=== 原始宽格式数据 === product North South East 0 A 100 180 190 1 B 150 170 ...
コードの解説:
stack()とunstack()は互いに逆の操作です。- 最初に stack してから unstack すると、理論上は元の形状に戻せます(埋め合わせ値の違いは無視)。
- 異なる level の組み合わせにより、異なるデータ配置を実現できます。
- 実際のデータ分析では、さまざまな分析ニーズに合わせてデータ形状を繰り返し調整する必要がよくあります。
その他の拡張ヒント:
unstack()とstack()はデータ再形成の中核ツールです。unstack()行を列に「分解」します(縦長→横長)。stack()列を行に「積み上げ」ます(横長→縦長)。
Pandas よく使う関数