機械学習データ前処理:行と列を入れ替えてデータを分析しやすい形にする方法【Pandas入門】
データ前処理において、元のデータを分析や機械学習モデルの入力に適した形に「整形」することは非常に重要です。多くの場合、取得した生データはそのままでは分析しにくく、行と列を入れ替えたり、特定の列を基準にデータを組み替えたりする必要があります。
本記事では、Pythonのデータ分析ライブラリであるPandasを使用して、データの形を変更する基本的な手法を解説します。特に、ビジネスの現場でよく使われるExcelのピボットテーブルに近い操作や、複数の列に分散したデータを集約する操作に焦点を当て、コード例を交えながら丁寧に説明します。
なぜデータの「形」を変える必要があるのか
データ分析や機械学習モデルの構築を行う際、データがどのような「形」をしているかは、その後の作業効率や分析結果に大きく影響します。例えば、アンケートデータのように「人」が行に、「質問項目」が列になっているデータもあれば、時系列データのように「時間」が行に、「観測値」が列になっているデータもあります。
多くの分析手法や機械学習ライブラリは、特定のデータの形(構造)を前提としています。例えば、ある列が特定のカテゴリを表し、別の列がそれに対応する数値を表すような形式(ロング形式と呼ばれることがあります)が適している場合もあれば、各行が一つの観測データを示し、各列がその特徴量を示す形式(ワイド形式と呼ばれることがあります)が適している場合もあります。
元のデータを目的の形に変換することで、はじめて適切な分析手法を適用したり、モデルにデータを与えたりすることが可能になります。
Pandasでデータを整形する基本的な手法
Pandasには、データの形を変更するための強力な機能がいくつか備わっています。ここでは、特によく利用される pivot_table
と melt
という2つの主要なメソッドを中心に解説します。
pivot_table: 横方向への集計・展開(Excelのピボットテーブルに似た操作)
pivot_table
メソッドは、指定した列のユニークな値を新しい列(またはインデックス)として展開し、同時にデータを集計する機能を提供します。これは、Excelのピボットテーブルでよく行う操作に非常に似ています。
例えば、「日付」「店舗」「売上」のようなデータがあったときに、「日付」を行に、「店舗」を列に、「売上」を値として集計する、といったことが可能です。
具体的な例を見てみましょう。以下のような架空の売上データがあるとします。
import pandas as pd
import numpy as np
# サンプルデータの作成
data = {
'日付': ['2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02', '2023-01-01', '2023-01-02'],
'店舗': ['A', 'B', 'A', 'C', 'C', 'B'],
'カテゴリ': ['食品', '食品', '衣類', '食品', '衣類', '衣類'],
'売上': [1000, 1500, 2000, 1200, 3000, 2500]
}
df = pd.DataFrame(data)
# 日付列をdatetime型に変換
df['日付'] = pd.to_datetime(df['日付'])
print("元のデータフレーム:")
print(df)
元のデータフレーム:
日付 店舗 カテゴリ 売上
0 2023-01-01 A 食品 1000
1 2023-01-01 B 食品 1500
2 2023-01-02 A 衣類 2000
3 2023-01-02 C 食品 1200
4 2023-01-01 C 衣類 3000
5 2023-01-02 B 衣類 2500
このデータを、「日付」を行インデックス、「店舗」を列、「売上」を値として集計し、店舗ごとの日別売上を把握したいとします。pivot_table
を使用すると、以下のように簡単に実現できます。
# pivot_tableを使用してデータを整形・集計
pivot_df = pd.pivot_table(
df,
values='売上', # 値として使用する列
index='日付', # 新しい行インデックスにする列
columns='店舗', # 新しい列にする列
aggfunc='sum', # 集計方法(合計)
fill_value=0 # 集計対象がなかった場合の欠損値を0で埋める
)
print("\npivot_tableで整形したデータフレーム:")
print(pivot_df)
pivot_tableで整形したデータフレーム:
店舗 A B C
日付
2023-01-01 1000 1500 3000
2023-01-02 2000 2500 1200
このように、pivot_table
を使うことで、元のデータを行と列に展開し、同時に指定した方法で値を集計した新しいデータフレームを作成できます。aggfunc
には 'mean' (平均) や 'count' (件数) など、さまざまな集計関数を指定できます。
melt: 縦方向への展開(複数の列を一つの列にまとめる)
melt
メソッドは、複数の列に分散しているデータを、特定の識別子列に基づいて縦方向(ロング形式)に積み上げるように整形します。これは pivot_table
とは逆の操作と考えることができます。
例えば、「年度」が行インデックスで、「地域Aの売上」「地域Bの売上」「地域Cの売上」が列になっているようなデータがあったときに、これを「年度」「地域」「売上」という3つの列を持つロング形式のデータに変換したい場合などに melt
が役立ちます。
多くの統計モデルや機械学習ライブラリ、特にグラフ描画ライブラリ(Seabornなど)は、このようなロング形式のデータを入力として要求することが多いため、melt
は非常に重要な整形手法です。
先ほどの pivot_table
の結果として得られたデータフレームを、元の「日付」「店舗」「売上」のようなロング形式に戻してみましょう。
# meltを使用してデータを縦方向に展開
melted_df = pd.melt(
pivot_df.reset_index(), # pivot_dfのインデックス(日付)を列に戻す
id_vars='日付', # 識別子としてそのまま残す列
var_name='店舗', # 展開した列名(店舗名)を格納する新しい列の名前
value_name='売上' # 展開した値(売上)を格納する新しい列の名前
)
print("\nmeltで整形したデータフレーム:")
print(melted_df)
meltで整形したデータフレーム:
日付 店舗 売上
0 2023-01-01 A 1000
1 2023-01-02 A 2000
2 2023-01-01 B 1500
3 2023-01-02 B 2500
4 2023-01-01 C 3000
5 2023-01-02 C 1200
melt
メソッドでは、id_vars
で「そのまま残したい列」を指定し、それ以外の列が縦方向に積み上げられます。積み上げられた元の列名(この場合は店舗名 A, B, C)は var_name
で指定した新しい列に、対応する値(この場合は売上)は value_name
で指定した新しい列に格納されます。
注意点として、melt
は集計を伴わないため、元の pivot_table
を melt
しても必ずしも元の集計前のデータフレーム(この場合は df
)と完全に同じ並びや形になるとは限りません。しかし、データの「ロング形式」という構造としては同じものになります。
まとめ
本記事では、Pandasを使ってデータの形を分析しやすいように変更する、基本的な整形方法を解説しました。
pivot_table
を使うことで、Excelのピボットテーブルのようにデータを横方向に展開し、集計することができます。melt
を使うことで、複数の列に分散したデータを縦方向に集約し、ロング形式に変換することができます。
これらのデータの整形スキルは、その後のデータ分析や機械学習モデル構築の土台となります。取得したデータは必ずしも分析に適した形をしているわけではないため、今回ご紹介した pivot_table
や melt
といった手法を活用して、データを適切な形に整えるプロセスを理解することは、データ前処理において非常に重要です。
データ前処理には様々なステップがありますが、データの形を理解し、必要に応じて整形することは、その後のステップを円滑に進めるための鍵となります。本記事が、皆様のデータ前処理スキルの向上の一助となれば幸いです。