Pandas df.unstack() 関数

Pandas 常用函数Pandas よく使う関数


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'])

実行結果の期待値:

=== 原始长格式数据 ===
  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

コードの解説:

  1. 元のデータは縦長形式で、各行に各製品の各地区での売上が記録されています。
  2. set_index をset_index()使用して階層化インデックスを作成します(product が外側、region が内側)。
  3. unstack()内側インデックス region を列の位置に移動します。
  4. 結果は横長形式になり、さまざまな製品の各地区での販売データを直感的に比較できます。

例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'])

実行結果の期待値:

=== 原始数据 ===
   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()}")

実行結果の期待値:

=== 原始数据(不完整)===
  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'))

実行結果の期待値:

=== 原始宽格式数据 ===
  product  North  South  East
0       A    100    180   190
1        B    150    170 
...

コードの解説:

  • stack()とunstack()は互いに逆の操作です。
  • 最初に stack してから unstack すると、理論上は元の形状に戻せます(埋め合わせ値の違いは無視)。
  • 異なる level の組み合わせにより、異なるデータ配置を実現できます。
  • 実際のデータ分析では、さまざまな分析ニーズに合わせてデータ形状を繰り返し調整する必要がよくあります。

ヒント: unstack()とstack()はデータ再形成の中核ツールです。unstack()行を列に「分解」します(縦長→横長)。stack()列を行に「積み上げ」ます(横長→縦長)。

Pandas 常用函数Pandas よく使う関数

その他の拡張