Pandasでは様々なデータを加工、整形することができますが、その中の機能としてある条件でデータを集計することができます。
今回はPandasの集計関数であるgroupbyを用いてデータを集約・集計する方法を紹介します。
使用するデータ
今回はMicrosoftの株価データを使います。集計しやすいように、予め日付データを年月に分割しておきます。
import pandas as pd
df = pd.read_csv("input/Microsoft_Stock.csv")
#Date型へ変換
df["Date"] = pd.to_datetime(df["Date"])
# Year列とMonth列を作成
df["Year"] = df["Date"].dt.year
df["Month"] = df["Date"].dt.month
今回は、2015/4/1 – 2021/3/31の期間で1日おきの株価データ(計1511件)です。
シンプルなgroupby
単一項目で集約
まずは最もシンプルな方法で集約します。例えば、年ごとの平均値を算出したい場合、”Year”列を用いて以下のようにします。
#単一項目でのGroupBy
df_agg = df.groupby("Year").mean()
年度ごとに集計されていることがわかります。集約に用いた項目(この場合は”Year”)はインデックスに割り当てられます。
gropubyをすると、集約できない文字列の属性等は除外されます。今回”Month”は数値型なので集計できてしまっていますが、実際は不要なので後続処理等で除外することになります。
複数項目で集約
上記データを年月で集約したい場合、”Year”、”Month”の2項目で集約することになります。その場合は、groupby()で渡す属性を配列で指定します。
#複数項目でのGroupBy
df_agg2 = df.groupby(["Year", "Month"]).mean()
集約に用いた”Year”、”Month”はマルチインデックスとして割り当てられます。
集計関数について
集計は平均(mean)だけでなく、一般的な集約関数は一通り使うことができます。
#様々な集計関数を適用可能
df_agg_sum = df.groupby("Year").sum()
df_agg_max = df.groupby("Year").max()
df_agg_min = df.groupby("Year").min()
グループラベルをインデックスに指定しない場合
集約に用いた項目(グループラベル)は、デフォルトでは集約後インデックスに割り当てられますが、as_index=Falseとすることで、元の列として残しておくことができます。
#グループのラベルをインデックスにしない場合
df_agg_no_index = df.groupby("Year", as_index=False).mean()
やや手の込んだgroupby
複数の集約結果を得たい場合
集約したのち、平均と総和両方を得たいという場合に、groupbyを2度実行するのは非効率です。その場合は、groupby()の後でagg()を追加します。サンプルを見たほうが早いので、以下に示します。以下は、合計値と集約件数を取得する場合です。
※ただしこれはPandasのバージョンが1.x以降の場合のみですので、ご注意ください
#複数の集約結果をまとめて取得したい場合(下記はpandas v1以降対応のフォーマット)
df_agg3 = df.groupby("Year").agg(["sum", "count"])
実行結果はマルチカラムの形で返されます。
関数を使った処理
集計値を計算した値(例:最大から最小を引いた値)を求めたい場合などでは、agg()を用いて関数適用することができます。
lambda関数を用いた処理
集約した後、lambda関数で最大値から最小値を引いた値を求めてみます。
#lambdaを使った処理も可能
df_agg4 = df.groupby("Year").agg(lambda x: max(x) - min(x))
python関数を用いる場合
通常の関数を呼び出して処理することもできます。
#関数を使うこともできる
def sample(x):
return max(x) - min(x)
df_agg5 = df.groupby("Year").agg(sample)
統計量のプロット
集約した結果を、グラフで表現することもできます。棒グラフの場合は以下のようにします。
#グループごとの統計量をプロットする(棒グラフ)
#Volumeは値が大きすぎるため除外
ax = df.drop("Volume", axis=1).groupby("Year").mean().plot(rot=0)
fig = ax.get_figure()
【参考】
#折れ線グラフの場合
ax = df.drop("Volume", axis=1).groupby("Year").mean().plot(rot=0)
fig = ax.get_figure()
Pythonでデータサイエンスするなら
Pythonでデータサイエンスをするなら、以下の書籍がおすすめです。Pandas、matplotlib、Numpy、scikit-learnといったデータサイエンスに必要なライブラリを、体系立てて一通り学ぶことができます。
ややお値段高めですが、これ1冊で十分という内容・ボリュームなので、損はしないと思います^^
初学者の方にはこちらもオススメです^^
まとめ
Pandasのgroupbyを使った集約・集計の方法を紹介しました。単純な集約(平均等)だけでなく、関数を用いたやや複雑な処理も可能なので、是非実践してみてください。
ではでは👋