データの形式には「縦持ち」と「横持ち」があります。pandas の melt を使うと、横持ちのデータを縦持ちに変換できます。これは pivot の逆操作にあたります。
縦持ちと横持ちの違い
まず、2 つの形式の違いを確認しましょう。
横持ち(ワイド形式)
1 行に複数の測定値が並ぶ。人間が見やすい形式。Excel のような表計算ソフトでよく使われる。
縦持ち(ロング形式)
1 行に 1 つの測定値。列数が少なく、行数が多い。統計処理や可視化ライブラリで扱いやすい。
たとえば、テストの点数データを考えてみます。
import pandas as pd
# 横持ち
df_wide = pd.DataFrame({
'name': ['Alice', 'Bob'],
'math': [80, 70],
'english': [90, 85]
})
print(df_wide)
これを縦持ちに変換すると、以下のようになります。
# 縦持ち
df_long = pd.DataFrame({
'name': ['Alice', 'Alice', 'Bob', 'Bob'],
'subject': ['math', 'english', 'math', 'english'],
'score': [80, 90, 70, 85]
})
print(df_long)
melt の基本的な使い方
melt を使って横持ちから縦持ちに変換します。
df_wide = pd.DataFrame({
'name': ['Alice', 'Bob'],
'math': [80, 70],
'english': [90, 85]
})
df_long = pd.melt(df_wide, id_vars=['name'], var_name='subject', value_name='score')
print(df_long)
主要なパラメータは以下の通りです。
| パラメータ | 説明 |
|---|---|
| id_vars | そのまま残す列 |
| var_name | 変換後の列名(元の列名が値になる) |
| value_name | 変換後の値の列名 |
複数の識別列を指定する
id_vars には複数の列を指定できます。
df = pd.DataFrame({
'year': [2023, 2024],
'name': ['Alice', 'Bob'],
'q1': [100, 150],
'q2': [120, 180]
})
df_long = pd.melt(df, id_vars=['year', 'name'], var_name='quarter', value_name='sales')
year と name はそのまま残り、q1 と q2 が縦に展開されます。
特定の列だけを変換する
value_vars を指定すると、変換する列を限定できます。
df = pd.DataFrame({
'name': ['Alice'],
'math': [80],
'english': [90],
'note': ['Good']
})
# math と english だけを変換、note は無視
df_long = pd.melt(df, id_vars=['name'], value_vars=['math', 'english'],
var_name='subject', value_name='score')
pivot で元に戻す
縦持ちから横持ちに戻すには pivot を使います。
df_long = pd.DataFrame({
'name': ['Alice', 'Alice', 'Bob', 'Bob'],
'subject': ['math', 'english', 'math', 'english'],
'score': [80, 90, 70, 85]
})
df_wide = df_long.pivot(index='name', columns='subject', values='score')
df_wide = df_wide.reset_index() # インデックスを列に戻す
melt と pivot は互いに逆の操作になります。データの形式を変換する必要があるときは、この 2 つを使い分けてください。可視化ライブラリの seaborn などは縦持ちのデータを好むことが多いので、melt で変換してからグラフを描くことがよくあります。