データの形式には「縦持ち」と「横持ち」があります。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 で変換してからグラフを描くことがよくあります。