Pandas pd.melt() 関数
pd.melt()は Pandas ライブラリのトップレベル関数であり、ワイド形式からロング形式への変換に使用されます。複数の列を含むワイド形式データを「溶かして」ロング形式に変換し、Excel のピボット解除操作に似ています。
これはデータ再形成で最もよく使われる関数の1つです。特にデータ可視化の前にデータをロング形式に変換する必要がある場合や、複数の列を1つの列にまとめたい場合に非常に便利です。
単語の意味: melt「溶かす、溶融する」という意味です。ここではワイド形式の構造をロング形式の構造に「溶かす」ことを指し、複数の列のデータを1か所に集めるようなイメージです。
基本構文とパラメータ
pd.melt()は Pandas ライブラリのトップレベル関数で、ワイド形式のデータをロング形式に変換するために使用します。
構文形式
pd.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)
パラメータの説明
- パラメータ:
frame- 型: DataFrame。
- 説明:必須パラメータ。元となる DataFrame、つまりワイド形式からロング形式に変換するデータです。
- パラメータ:
id_vars- 型: 列名、タプルのリスト、または None。
- 説明: 識別子(ID)として使用する列で、変換後もそのまま保持されます。単一の列名または列名のリストを指定できます。指定しない場合、すべての列が value_vars とみなされます。
- パラメータ:
value_vars- 型: 列名、タプルのリスト、または None。
- 説明: 「溶かす」列、つまりどの列を行に変換するかを指定します。指定しない場合、id_vars 以外のすべての列が変換されます。
- パラメータ:
var_name- 型: 文字列または None。
- 説明: 元の列名を格納するために生成される新しい列名です。デフォルトは 'variable' です。
- パラメータ:
value_name- 型: 文字列。
- 説明: 生成される値の列名です。デフォルトは 'value' です。
- パラメータ:
col_level- 型: int、str、または None。
- 説明: 列が MultiIndex(マルチレベルインデックス)の場合、溶かすレベルを指定します。
関数の説明
- 戻り値: ワイド形式からロング形式に変換された DataFrame を返します。
- 効果: 複数の列の値を2つの列に「溶かします」。1つの列には元の列名(variable)が格納され、もう1つの列には対応する値(value)が格納されます。
例
簡単な例から複雑な例までの一連の例を通して、pd.melt()pd.melt() の使い方を完全にマスターしましょう。
例1: 基本的な使い方 - シンプルなワイド形式からロング形式への変換
例
# 1. ワイド形式データの作成(各四半期に1列)
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'Q1_sales': [100, 150, 200],
'Q2_sales': [120, 160, 210],
'Q3_sales': [130, 170, 220]
})
print("=== 元のワイド形式データ ===")
print(df)
# 2. pd.melt() を使ってロング形式に変換
melted = pd.melt(df, id_vars=['name'], value_vars=['Q1_sales', 'Q2_sales', 'Q3_sales'])
print("n=== pd.melt() でロング形式に変換 ===")
print(melted)
# 3. 列名をカスタマイズ
melted_custom = pd.melt(
df,
id_vars=['name'],
value_vars=['Q1_sales', 'Q2_sales', 'Q3_sales'],
var_name='quarter',
value_name='sales'
)
print("n=== カスタマイズした列名 ===")
print(melted_custom)
実行結果の想定:
=== 原始宽格式数据 ===
name Q1_sales Q2_sales Q3_sales
0 Alice 100 120 130
1 Bob 150 160 170
2 Charlie 200 210 220
=== pd.melt() 转换为长格式 ===
name variable value
0 Alice Q1_sales 100
1 Bob Q1_sales 150
2 Charlie Q1_sales 200
3 Alice Q2_sales 120
4 Bob Q2_sales 160
5 Charlie Q2_sales 210
6 Alice Q3_sales 130
7 Bob Q3_sales 170
8 Charlie Q3_sales 220
=== 自定义列名 ===
name quarter sales
0 Alice Q1_sales 100
1 Bob Q1_sales 150
2 Charlie Q1_sales 200
3 Alice Q2_sales 200
コード解説:
- 元データはワイド形式で、各行が1人を表し、Q1、Q2、Q3 は3つの四半期の売上データ列です。
id_vars=['name']name 列を識別子として指定し、そのまま保持します。value_vars=['Q1_sales', 'Q2_sales', 'Q3_sales']溶かす列を指定します。- 結果には variable 列(元の列名を格納)と value 列(対応する値を格納)が追加されます。
- 使用することで、
var_nameとvalue_name新しい列の名前をカスタマイズできます。
例2: value_vars を指定しない - id_vars 以外のすべての列を溶かす
value_vars を指定しない場合、id_vars 以外のすべての列が自動的に溶かされます。
例
# 1. より多くの列を含むデータを作成
df = pd.DataFrame({
'id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Charlie'],
'math': [90, 85, 92],
'english': [88, 90, 87],
'science': [95, 88, 91]
})
print("=== 元のデータ ===")
print(df)
# 2. id_vars のみを指定し、他のすべての列を自動的に溶かす
melted = pd.melt(df, id_vars=['id', 'name'])
print("n=== すべての非id列を溶かす ===")
print(melted)
# 3. 複数の id_vars の場合
print("n=== 複数の id_vars ===")
melted_multi = pd.melt(df, id_vars=['name'], value_vars=['math', 'english', 'science'])
print(melted_multi)
# 4. 1つの id_vars のみを使用
print("n=== 1つの id_vars ===")
melted_one = pd.melt(df, id_vars=['id'])
print(melted_one)
実行結果の想定:
=== 原始数据 === id name math english science 0 1 Alice 90 88 95 1 2 Bob 85 90 88 2 3 Charlie 92 87 91 === 融化所有非id列 === id name variable value 0 1 Alice math 90 1 2 Bob math 85 2 3 Charlie math 92 3 1 Alice english 88 4 2 融化为两列(variable 和 value)。 - 不指定 value_vars 时,系统会自动识别并熔化除 id_vars 外的所有列 - id_vars 可以是单个列或多个列的组合
コード解説:
- value_vars を指定しない
value_vars場合、自動的に溶かされるのはid_vars以外のすべての列です。 - id_vars のみで value_vars がない場合、各データ行は value_vars の数に応じた数の新しい行を生成します。
- この方法は、複数の列のデータをまとめて処理する必要がある場合に非常に便利です。
例3: id_vars なし - すべての列を溶かす
id_vars を指定しない場合、元のデータのインデックスが識別子として使用されます。
例
# 1. データの作成(明確なID列がない)
df = pd.DataFrame({
'Q1': [100, 150, 200],
'Q2': [120, 160, 210],
'Q3': [130, 170, 220]
})
print("=== 元のデータ ===")
print(df)
# 2. id_vars を指定せず、デフォルトのインデックスを使用
melted = pd.melt(df)
print("n=== id_vars を指定しない ===")
print(melted)
# 3. 元のインデックスを復元
print("n=== インデックスをリセット ===")
melted_with_index = pd.melt(df, ignore_index=False)
print(melted_with_index)
# 4. 実用的な例:識別子の作成
df_with_id = pd.DataFrame({
'year': [2023, 2023, 2023],
'Q1': [100, 150, 200],
'Q2': [120, 160, 210]
})
print("n=== 元のデータ(年あり)===")
print(df_with_id)
# 最初に year を id_vars に追加
melted_year = pd.melt(df_with_id, id_vars=['year'])
print("n=== 年を含む melt 結果 ===")
print(melted_year)
実行結果の想定:
=== 原始数据 ===
Q1 Q2 Q3
0 100 120 130
1 150 160 170
2 200 210 220
=== 不指定 id_vars ===
variable value
0 Q1 100
1 Q1 150
2 融化所有列,将原始列名转为 variable 列的值,原始值转为 value 列。
コード解説:
- id_vars を指定しない場合、variable と value の2列だけが残ります。
- 使用することで、
ignore_index=False元のインデックスを保持でき、後で元データと比較するのに便利です。 - 実際の使用では、通常1つ以上の id_vars を指定して重要な情報を保持します。
例4: 実用的な例 - データ可視化の前準備
melt() はデータ可視化の強い味方です。多くのプロットライブラリ(Seaborn、Matplotlib など)はロング形式のデータをより得意としています。
例
# 1. 売上データの作成(各地区に1列)
sales = pd.DataFrame({
'product': ['A', 'B', 'C', 'D'],
'Jan': [1200, 1500, 900, 1100],
'Feb': [1350, 1600, 950, 1200],
'Mar': [1100, 1450, 880, 1050]
})
print("=== ワイド形式の売上データ ===")
print(sales)
# 2. ロング形式に溶かす(可視化用)
sales_long = pd.melt(
sales,
id_vars=['product'],
var_name='month',
value_name='sales'
)
print("n=== ロング形式の売上データ ===")
print(sales_long)
# 3. データ処理の例:前年比の計算
# 月番号を追加
month_map = {'Jan': 1, 'Feb': 2, 'Mar': 3}
sales_long['month_num'] = sales_long['month'].map(month_map)
print("n=== 月番号を追加 ===")
print(sales_long)
# 4. 特定の月のデータを抽出
feb_sales = sales_long[sales_long['month'] == 'Feb']
print("n=== 2月の売上データ ===")
print(feb_sales)
実行結果の想定:
=== 宽格式销售数据 === product Jan Feb Mar 0 A 1200 1350 1100 product Jan 180 170 6 === 长格式销售数据(用于可视化) === product month sales 0 A Jan 1200 1 B Jan 1500 2 C Jan 900 3 D Jan 1100 4 A Feb 1350
コード解説:
- ワイド形式のデータは地区・時点ごとに1列あるため、確認や入力がしやすいです。
- ロング形式のデータは各観測値が1行になり、統計分析の標準的な形式です。
- Seaborn などの可視化ライブラリはロング形式のデータを受け入れ、グループ化された棒グラフや折れ線グラフなどを簡単に作成できます。
- 使用することで、
id_vars製品や地区などのカテゴリ変数を溶かさずに保持できます。
例5: マルチレベルの列インデックスの溶融
DataFrame にマルチレベルの列インデックスがある場合は、col_levelパラメータを使用できます。
例
# 1. マルチレベルの列インデックスを持つデータを作成
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=['Category', 'Quarter'])
)
print("=== 元のデータ(マルチレベル列インデックス)===")
print(df)
# 2. すべての列を溶かす(レベルを指定しない)
print("n=== すべての列を溶かす ===")
melted_all = pd.melt(df, ignore_index=False)
print(melted_all)
# 3. 内側のレベル(Quarter)のみを溶かす
print("n=== Quarter レベルだけを溶かす ===")
melted_quarter = pd.melt(df, col_level=1)
print(melted_quarter)
# 4. 外側のレベル(Category)を溶かす
print("n=== Category 層のみを溶融 ===")
melted_category = pd.melt(df, col_level=0)
print(melted_category)
実行結果の予想:
=== 原始数据(多层列索引)=== Category Electronics Furniture Quarter Q1 Q2 Q1 融化不同层级会产生不同的结果: - 融化内层(Quarter)保留 Category 作为 id - 融化外层(Category)保留 Quarter 作为 id
コード解析:
- 多層列インデックスの DataFrame で、列名はタプル形式です:(Category, Quarter)。
col_level=0外側の層(Category)を溶融し、Quarter を id として保持します。col_level=1内側の層(Quarter)を溶融し、Category を id として保持します。- この柔軟性により、分析のニーズに応じて溶融する階層を選択できます。
その他の拡張ヒント:
pd.melt()データ可視化の優れた助っ人です。多くの描画ライブラリ(Seaborn、Plotnine など)はロングフォーマットデータの処理が得意なため、最初に melt() でデータを変換してから描画するのが一般的な方法です。