Pandas df.stack() 関数
df.stack()DataFrame のメンバーメソッドであり、列インデックスを行インデックスに変換するために使用されます。これはワイド形式データの列を「スタック」して行にし、階層化インデックスを持つ Series または DataFrame を生成します。
これはデータ再形成における重要な操作であり、通常はunstack()と組み合わせて使用することで、データの相互変換を実現します。
単語の説明: stackは「スタック、積み重ね」を意味し、ここでは列データを「スタック」して行にし、ワイドテーブルをロングテーブルに変換することを指します。
基本構文とパラメータ
df.stack()DataFrame のインスタンスメソッドであり、ドット演算子によって呼び出されます。
構文形式
DataFrame.stack(level=-1, dropna=True)
パラメータの説明
- パラメータ:
level- 型: int、str、int リスト、または str リスト。
- 説明: スタックするレベルを指定します。複数層インデックスの場合、具体的なレベル番号(0から始まる)またはレベル名を指定できます。デフォルトは -1 で、最内層を表します。
- パラメータ:
dropna- 型: ブール値。
- 説明: 結果内のすべてが NaN の行を削除するかどうか。デフォルトは True で、すべての値が NaN の行を削除します。
関数の説明
- 戻り値: Series または DataFrame を返します。元の DataFrame でスタックされる列が1つだけの場合は Series を返し、それ以外の場合は DataFrame を返します。
- 効果: 列インデックスを行インデックスに変換し、より長いデータ形式を生成します。スタック後のデータは「ロング形式」であり、統計分析や可視化に適しています。
例
単純なものから複雑なものまでの一連の例を通して、df.stack()の使い方を徹底的に習得しましょう。
例1:基本的な使い方 - 列を行に変換
例
import pandas as pd
import numpy as np
# 1. ワイド形式のデータを作成(四半期ごとに1列)
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'Q1': [100, 150, 200],
'Q2': [120, 160, 210],
'Q3': [130, 170, 220]
})
print("=== 元のワイド形式データ ===")
print(df)
print(f"列名: {df.columns.tolist()}")
# 2. df.stack() を使用して列を行に変換
stacked = df.stack()
print("n=== df.stack() 結果 ===")
print(stacked)
print(f"n型: {type(stacked)}")
# 3. 結果をDataFrameに変換して確認
print("n=== DataFrameに変換 ===")
stacked_df = stacked.reset_index()
stacked_df.columns = ['name', 'quarter', 'sales']
print(stacked_df)
import numpy as np
# 1. ワイド形式のデータを作成(四半期ごとに1列)
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'Q1': [100, 150, 200],
'Q2': [120, 160, 210],
'Q3': [130, 170, 220]
})
print("=== 元のワイド形式データ ===")
print(df)
print(f"列名: {df.columns.tolist()}")
# 2. df.stack() を使用して列を行に変換
stacked = df.stack()
print("n=== df.stack() 結果 ===")
print(stacked)
print(f"n型: {type(stacked)}")
# 3. 結果をDataFrameに変換して確認
print("n=== DataFrameに変換 ===")
stacked_df = stacked.reset_index()
stacked_df.columns = ['name', 'quarter', 'sales']
print(stacked_df)
実行結果の予想:
=== 原始宽格式数据 ===
name Q1 Q2 Q3
0 Alice 100 120 130
1 Bob 150 160 170
2 Charlie 'Q2', 'Q3'], columns=['name', 'quarter', 'sales']
...
コードの解説:
- 元のデータはワイド形式で、Q1、Q2、Q3 は3つの四半期データの列です。
stack()Q1、Q2、Q3 の3列を「スタック」して行にします。- 結果は Series 型で、2層のインデックスを含みます:外側は元の行インデックス、内側は元の列名(四半期)です。
- スタック後、データは「ロング形式」になり、各行には1つの四半期の値だけが含まれます。
例2:複数層の列インデックスのスタック
DataFrame に複数層の列インデックスがある場合、スタックするレベルを指定できます。
例
import pandas as pd
import numpy as np
# 1. 複数層の列インデックスを持つデータを作成
# 外側:製品タイプ(Electronics、Furniture)
# 内側:四半期(Q1、Q2)
df = pd.DataFrame(
[[100, 110, 200, 210], [150, 160, 180, 190]],
index=['Store_A', 'Store_B'],
columns=pd.MultiIndex.from_tuples([
('Electronics', 'Q1'), ('Electronics', 'Q2'),
('Furniture', 'Q1'), ('Furniture', 'Q2')
], names=['Product', 'Quarter'])
)
print("=== 元のデータ(複数層の列インデックス)===")
print(df)
print(f"列インデックスのレベル: {df.columns.names}")
# 2. 内側の列をスタック(デフォルト、level=-1)
print("n=== 内側の列をスタック (level=-1) ===")
stacked_inner = df.stack()
print(stacked_inner)
# 3. 外側の列をスタック
print("n=== 外側の列をスタック (level=0) ===")
stacked_outer = df.stack(level=0)
print(stacked_outer)
# 4. すべての列をスタック(より長い形式を生成)
print("n=== すべての列をスタック ===")
stacked_all = df.stack(level=[0, 1])
print(stacked_all)
import numpy as np
# 1. 複数層の列インデックスを持つデータを作成
# 外側:製品タイプ(Electronics、Furniture)
# 内側:四半期(Q1、Q2)
df = pd.DataFrame(
[[100, 110, 200, 210], [150, 160, 180, 190]],
index=['Store_A', 'Store_B'],
columns=pd.MultiIndex.from_tuples([
('Electronics', 'Q1'), ('Electronics', 'Q2'),
('Furniture', 'Q1'), ('Furniture', 'Q2')
], names=['Product', 'Quarter'])
)
print("=== 元のデータ(複数層の列インデックス)===")
print(df)
print(f"列インデックスのレベル: {df.columns.names}")
# 2. 内側の列をスタック(デフォルト、level=-1)
print("n=== 内側の列をスタック (level=-1) ===")
stacked_inner = df.stack()
print(stacked_inner)
# 3. 外側の列をスタック
print("n=== 外側の列をスタック (level=0) ===")
stacked_outer = df.stack(level=0)
print(stacked_outer)
# 4. すべての列をスタック(より長い形式を生成)
print("n=== すべての列をスタック ===")
stacked_all = df.stack(level=[0, 1])
print(stacked_all)
実行結果の予想:
=== 原始数据(多层列索引)=== Product Electronics Furniture Quarter Q1 Q2 Q1 Q ...
コードの解説:
- 複数層の列インデックスを持つ DataFrame では、列名はタプル形式です:(Product, Quarter)。
level=-1(デフォルト)最内層、つまり Quarter 層をスタックし、結果は Product を列として保持します。level=0外側の層、つまり Product 層をスタックし、結果は Quarter を列として保持します。- この柔軟性により、分析のニーズに応じてスタックするレベルを選択できます。
例3:欠損値の処理
使用dropnaパラメータで欠損値の処理方法を制御します。
例
import pandas as pd
import numpy as np
# 1. 欠損値を含むデータを作成
df = pd.DataFrame({
'name': ['Alice', 'Bob'],
'Math': [100, np.nan],
'English': [90, 85],
'Science': [np.nan, 95]
})
print("=== 元のデータ(欠損値を含む)===")
print(df)
# 2. dropna=True(デフォルト)、すべてがNaNの行を削除
print("n=== dropna=True(デフォルト)===")
stacked_drop = df.stack(dropna=True)
print(stacked_drop)
# 3. dropna=False、NaN値を保持
print("n=== dropna=False ===")
stacked_keep = df.stack(dropna=False)
print(stacked_keep)
# 4. 実際の応用:スタック結果を分析可能なロング形式に整理
print("n=== ロング形式のDataFrameに整理 ===")
result = df.set_index('name').stack().reset_index()
result.columns = ['name', 'subject', 'score']
print(result)
# 5. 欠損値を削除
result_clean = result.dropna()
print("n=== 欠損値の削除後 ===")
print(result_clean)
import numpy as np
# 1. 欠損値を含むデータを作成
df = pd.DataFrame({
'name': ['Alice', 'Bob'],
'Math': [100, np.nan],
'English': [90, 85],
'Science': [np.nan, 95]
})
print("=== 元のデータ(欠損値を含む)===")
print(df)
# 2. dropna=True(デフォルト)、すべてがNaNの行を削除
print("n=== dropna=True(デフォルト)===")
stacked_drop = df.stack(dropna=True)
print(stacked_drop)
# 3. dropna=False、NaN値を保持
print("n=== dropna=False ===")
stacked_keep = df.stack(dropna=False)
print(stacked_keep)
# 4. 実際の応用:スタック結果を分析可能なロング形式に整理
print("n=== ロング形式のDataFrameに整理 ===")
result = df.set_index('name').stack().reset_index()
result.columns = ['name', 'subject', 'score']
print(result)
# 5. 欠損値を削除
result_clean = result.dropna()
print("n=== 欠損値の削除後 ===")
print(result_clean)
実行結果の予想:
=== 原始数据(包含缺失值)===
name Math English Science
0 Alice 100.0 90.0 NaN
1 Bob NaN 85.0 95.0
2=== 堆叠内层列 (level=-1) ===
Store_A Electronics Q1 100
Q2 110
Furniture Q1 200
Q2 210
Store_B Electronics Q1 150
...
コードの解説:
dropna=True(デフォルト)すべての値が NaN の行を削除します。- データ分析では、通常は元のデータを保持し、必要に応じて欠損値を削除します。
- スタック後に使用
reset_index()すると、階層インデックスを通常の列に変換でき、後続の処理が容易になります。
例4:stack と unstack の組み合わせ使用
stack()とunstack()は互いに逆の操作であり、組み合わせて使用することで、データの柔軟な再形成を実現できます。
例
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. unstack を使用して地区を列に変換(先に複数層インデックスに変換)
df_indexed = df.set_index('product')
print("n=== インデックス設定後 ===")
print(df_indexed)
# 3. stack を使用して列を行に変換(stackはunstackの逆操作)
print("n=== unstack + stack 往復 ===")
# 最初に unstack
unstacked = df_indexed.unstack()
print("unstack 結果:")
print(unstacked)
# 次に stack で戻す
restacked = unstacked.stack()
print("nstack で元に戻す:")
print(restacked)
# 4. 完全な例:複数層インデックスを作成してから変換
print("n=== 複数層インデックスの変換 ===")
# 複数層インデックスのDataFrameを作成
multi_df = pd.DataFrame(
[[100, 110], [150, 160]],
index=pd.MultiIndex.from_tuples([('A', '2023'), ('B', '2023')], names=['product', 'year']),
columns=['North', 'South']
)
print("元の複数層インデックスデータ:")
print(multi_df)
# unstack year
print("nunstack year:")
print(multi_df.unstack(level='year'))
# unstack columns
print("nunstack columns (列に変換):")
print(multi_df.unstack(level='columns'))
# 1. 初期データを作成
df = pd.DataFrame({
'product': ['A', 'B', 'C'],
'North': [100, 150, 200],
'South': [180, 170, 160],
'East': [190, 200, 210]
})
print("=== 元のデータ ===")
print(df)
# 2. unstack を使用して地区を列に変換(先に複数層インデックスに変換)
df_indexed = df.set_index('product')
print("n=== インデックス設定後 ===")
print(df_indexed)
# 3. stack を使用して列を行に変換(stackはunstackの逆操作)
print("n=== unstack + stack 往復 ===")
# 最初に unstack
unstacked = df_indexed.unstack()
print("unstack 結果:")
print(unstacked)
# 次に stack で戻す
restacked = unstacked.stack()
print("nstack で元に戻す:")
print(restacked)
# 4. 完全な例:複数層インデックスを作成してから変換
print("n=== 複数層インデックスの変換 ===")
# 複数層インデックスのDataFrameを作成
multi_df = pd.DataFrame(
[[100, 110], [150, 160]],
index=pd.MultiIndex.from_tuples([('A', '2023'), ('B', '2023')], names=['product', 'year']),
columns=['North', 'South']
)
print("元の複数層インデックスデータ:")
print(multi_df)
# unstack year
print("nunstack year:")
print(multi_df.unstack(level='year'))
# unstack columns
print("nunstack columns (列に変換):")
print(multi_df.unstack(level='columns'))
実行結果の予想:
=== unstack + stack 往返 ===
unstack 结果:
product
North A 100
B 150
C 200
South A 180
B 170
...
コードの解説:
stack()列インデックスを行インデックスに変換し、ワイドテーブルをロングテーブルに変換します。unstack()行インデックスを列インデックスに変換し、ロングテーブルをワイドテーブルに変換します。- 両者を組み合わせて使用することで、データを任意の形状に変換できます。
- データ分析において、これら2つの操作の互いに逆の関係を理解することは非常に重要です。
その他の拡張ヒント:
stack()とunstack()はデータ再形成の中核的なツールです。stack()列を「スタック」して行にします(ワイドからロングへ)、unstack()行を「展開」して列にします(ロングからワイドへ)。
Pandas よく使う関数