Python | データ処理:melt

Python
スポンサーリンク

概要(meltは「横持ちの列を縦に溶かして整然データへ変換する」)

pandasのmeltは、ワイド形式(横持ち)をロング形式(縦持ち)へ変換するためのメソッドです。列として並んだ複数の計測値(例: Math, English, Science)を「変数名(var_name)」「値(value_name)」の2列にまとめ、分析や可視化に使いやすい“整然データ”へ変えます。Excelの「ピボットの逆」をイメージすると掴みやすく、Seabornや集計処理との相性が抜群です。


基本の使い方(id_vars・value_vars・var_name・value_name)

最小例(教科ごとのスコア列を縦へ)

import pandas as pd

df = pd.DataFrame({
    "ID": [1, 2, 3],
    "Name": ["Alice", "Bob", "Charlie"],
    "Math": [90, 80, 85],
    "English": [85, 95, 90],
})

melted = df.melt(
    id_vars=["ID", "Name"],      # そのまま残す識別列
    value_vars=["Math", "English"],  # 縦へ溶かす対象列
    var_name="Subject",          # 列名を格納する列名
    value_name="Score"           # 値を格納する列名
)
print(melted)
#    ID     Name  Subject  Score
# 0   1    Alice     Math     90
# 1   2      Bob     Math     80
# 2   3  Charlie     Math     85
# 3   1    Alice  English     85
# 4   2      Bob  English     95
# 5   3  Charlie  English     90
Python

id_varsに主キーや識別情報を指定し、value_varsに“縦にしたい列”を指定します。var_nameとvalue_nameを付けると後工程で扱いやすくなります。

value_varsを省略して「id以外をすべて溶かす」

melted_all = df.melt(id_vars=["ID", "Name"], var_name="Subject", value_name="Score")
Python

対象列が多いときに便利です。id_varsで“残したい列”だけ指定し、他は全部縦持ちへ。


重要ポイントの深掘り(ignore_index・カテゴリ順・MultiIndex列)

ignore_indexで新しい連番インデックスへ

meltは元の行を複製して縦に増やすため、インデックスが重複しがちです。整形後の扱いやすさを優先するなら、reset_index(またはmelt後にreset_index)で連番へ振り直します。

melted = df.melt(id_vars=["ID", "Name"], var_name="Subject", value_name="Score").reset_index(drop=True)
Python

カテゴリ順の固定(並べ替えの安定化)

Subjectの表示順(例: Math→English→Science)を固定したいときは、カテゴリ型を使うとグラフや表の並びを安定させられます。

melted["Subject"] = pd.Categorical(melted["Subject"], categories=["Math", "English"], ordered=True)
Python

MultiIndex列を持つ場合のmelt(col_levelと階層の扱い)

列が階層(MultiIndex)になっている場合は、必要な階層だけを溶かす指定ができます。まずは列をフラット化してからmeltするのがわかりやすい定石です。

# 例:MultiIndex列をフラット化して扱いやすく
df.columns = ["_".join(map(str, c)).strip() if isinstance(c, tuple) else c for c in df.columns]
melted = df.melt(id_vars=["ID", "Name"], var_name="Variable", value_name="Value")
Python

col_levelを使う方法もありますが、初心者は「一度フラット化→通常のmelt」が確実です。


実践例(前処理・可視化・ピボットとの往復)

可視化へ直行できる形へ(Seabornのbarplotやlineplotにそのまま渡す)

import pandas as pd

df = pd.DataFrame({
    "Month": ["Jan", "Feb", "Mar"],
    "ProductA": [150, 160, 175],
    "ProductB": [90, 95, 110],
})

melted = df.melt(id_vars=["Month"], var_name="Product", value_name="Sales")
print(melted)
#   Month   Product  Sales
# 0   Jan  ProductA    150
# 1   Feb  ProductA    160
# 2   Mar  ProductA    175
# 3   Jan  ProductB     90
# 4   Feb  ProductB     95
# 5   Mar  ProductB    110

# 可視化例(コメント):sns.lineplot(data=melted, x="Month", y="Sales", hue="Product")
Python

「月×商品×売上」をロング形式にすると、色分けや凡例の制御が容易になります。

melt後に集計(groupby)で指標を作る

melted = df.melt(id_vars=["Month"], var_name="Product", value_name="Sales")
summary = (
    melted
    .groupby("Product", as_index=False)
    .agg(mean_sales=("Sales", "mean"), max_sales=("Sales", "max"))
)
print(summary)
Python

ロング形式はgroupbyと相性が良く、平均や最大などの集計が直感的に書けます。

pivot_table(またはpivot)で“元の形へ戻す”往復の流れ

# ロング→ワイド(合計例)
wide = pd.pivot_table(
    melted, index="Month", columns="Product", values="Sales", aggfunc="sum", fill_value=0
).reset_index()
print(wide)
Python

meltで縦へ、pivot_tableで横へ—この往復で、分析→出力(CSVや報告用の表)の両方に対応できます。重複がある現実データではpivotよりpivot_tableが安全です。


つまずき対策(識別列の消失・型の不一致・大規模データ)

識別列(id_vars)を忘れると紐付けが切れる

「誰のどの値か」を示す列(ID、日付、カテゴリなど)は必ずid_varsへ。これを忘れると、後工程でグループ化やフィルタができなくなります。

型の不一致を先に正規化(文字列・数値・日時)

溶かす対象列が文字列と数値で混在していると、value列のdtypeがobjectになりがちです。分析前にastypeで揃える、日時はto_datetimeで変換しておくと、後工程が安定します。

大規模データは段階処理で安全に

列数・行数が多い場合、いきなり全列をmeltせず、対象列を絞る→中間確認→追加、の段階処理が安全です。出力直前にはreset_indexで連番化、不要列のdropで軽量化しましょう。


例題(稼働指標のロング変換→比率計算→報告用に整形)

ワイドからロングへ溶かす

import pandas as pd

df = pd.DataFrame({
    "date": ["2025-01-01", "2025-01-02", "2025-01-03"],
    "active_users": [100, 120, 110],
    "new_users": [30, 40, 35],
    "churn_users": [5, 8, 6],
})

melted = df.melt(
    id_vars=["date"],
    value_vars=["active_users", "new_users", "churn_users"],
    var_name="metric",
    value_name="value"
)
print(melted.head())
Python

比率や派生指標を追加(後処理のコツ)

# 例:日ごとの「新規率」= new / active
pivoted = pd.pivot_table(melted, index="date", columns="metric", values="value", aggfunc="sum", fill_value=0)
pivoted["new_rate"] = (pivoted["new_users"] / pivoted["active_users"]).replace([float("inf")], 0).round(3)
print(pivoted.reset_index())
Python

meltで整然化→pivot_tableで集計・派生列追加の流れは、レポート作成の定番です。


まとめ(meltは“列を溶かして縦へ”。id_varsで紐付け、var/value名でわかりやすく)

meltは、横持ちの複数列を「変数名」と「値」にまとめ、整然データへ変換するための最短ルートです。id_varsで識別列を残し、value_varsで対象列を選び、var_name・value_nameで意味を明確化する。必要に応じてreset_indexで連番化し、カテゴリ順やdtypeを整える。整然化したロング形式は、groupby・可視化・pivot_tableとの往復で圧倒的に扱いやすくなります。これを型として身につければ、初心者でも“迷わず、速く、正確に”データ整形ができるようになります。

タイトルとURLをコピーしました