Pandas pd.melt() 関数

Pandas の常用関数


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: 基本的な使い方 - シンプルなワイド形式からロング形式への変換

例

import pandas as pd

# 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. 元データはワイド形式で、各行が1人を表し、Q1、Q2、Q3 は3つの四半期の売上データ列です。
  2. id_vars=['name']name 列を識別子として指定し、そのまま保持します。
  3. value_vars=['Q1_sales', 'Q2_sales', 'Q3_sales']溶かす列を指定します。
  4. 結果には variable 列(元の列名を格納)と value 列(対応する値を格納)が追加されます。
  5. 使用することで、var_nameとvalue_name新しい列の名前をカスタマイズできます。

例2: value_vars を指定しない - id_vars 以外のすべての列を溶かす

value_vars を指定しない場合、id_vars 以外のすべての列が自動的に溶かされます。

例

import pandas as pd

# 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 を指定しない場合、元のデータのインデックスが識別子として使用されます。

例

import pandas as pd

# 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 など)はロング形式のデータをより得意としています。

例

import pandas as pd

# 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パラメータを使用できます。

例

import pandas as pd

# 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() でデータを変換してから描画するのが一般的な方法です。

Pandas よく使う関数

その他の拡張