よっしーの私的空間

機械学習を中心に興味のあることについて更新します

横持ちデータを縦持ちデータに変換する方法(Pandas)

PythonのPandasで横持ちデータを縦持ちにデータに変換する方法についてまとめます。 縦持ちデータを横持ちデータに変換する方法については過去記事にまとめています。

1.実施内容(概要)

Pandasの以下のような横持ちデータを

氏名 数学 国語 英語 ドイツ語 アラビア語
A君 100 70 60 60 NaN
B君 60 50 50 NaN 60

以下のような縦持ちデータに変換します。

氏名 科目 点数
A君 数学 100
A君 国語 70
A君 英語 60
A君 ドイツ語 60
B君 数学 60
B君 国語 50
B君 英語 50
B君 アラビア語 60

縦持ちに変換するためにMelt関数を使用します。(公式ドキュメントはこちら

Melt関数は以下の通り使用します。

pandas.melt(frame, id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None)

それぞれの引数の解説は以下の通り。
frame:縦持ちに変換するデータフレーム。
id_vars:そのまま変形せずに残す列。今回の場合は「氏名」列のこと。
value_vars:縦持ちに変換する列。指定しない場合は、id_varsで指定していない全列を使用。
var_name:変数の列名。今回の例の場合は縦持ちにしたときの「科目」のこと。
value_name:値の列名。今回の例の場合は縦持ちにした時の「点数」のこと。
col_level:データフレームがマルチインデックスの場合、インデックスの数を指定。

2.実装方法

まずは以下のように横持ちデータのサンプルを作成します。

df_score_horizontal = pd.DataFrame([['A君',100,70,60,60,np.nan],
                                  ['B君',60,50,50,np.nan,60]],
                                 columns=['氏名','数学','国語','英語','ドイツ語','アラビア語'])

以下で横持ちを縦持ちに変換できます。

pd.melt(df_score_horizontal,
        id_vars=df_score_horizontal.columns.values[:1],
        var_name="科目",
        value_name="点数"
       )
  • id_varsで指定した列(氏名)はそのまま残しつつ、その他の列(数学~アラビア語)は縦持ちに変換する列として使用。
  • 横持ちのときは列名だった「数学~アラビア語」は縦持ちに変換するとデータ内に組み込まれるので、「数学~アラビア語」を総称する列名としてvar_name="科目"と指定。
  • 最後に縦持ちに変換した際のデータの総称をvalue_name="点数"と指定。