Numpyのみでグループ別に集計し平均を出す方法(for文、Pandasなし)
Posted On 2018-08-28
Numpy配列をグループ別に集計するときに、大抵Pandasを使うのですが、Numpyだけで集計するのってできるのかな?どうやるんだろうという話です。答えは「できます」。one-hotベクトルを使って集計する方法を紹介していきます。
このアイディアはTwitterで教えてもらったものです。教えてくださった方に感謝。
目次
データの用意
説明のためにIrisデータセットを使います。(花弁の長さ, アヤメの種類)の形式の配列を作ります。花弁の長さはcmで、アヤメの種類はSetosa, Versicolour, Virginicaの順に0,1,2とします。
from sklearn.datasets import load_iris
import numpy as np
iris = load_iris()
# [花弁の長さ, アヤメの種類]のデータを作る
data = np.c_[np.array(iris["data"][:,3]), np.array(iris["target"])]
print(data)
print()
このような配列です。
[[0.2 0. ]
[0.2 0. ]
[0.2 0. ]
(略)
[1.4 1. ]
[1.5 1. ]
[1.5 1. ]
(略)]
集計
アヤメの種類をOne-hotベクトル化します。これと集計したい花弁の長さのベクトルをかけ合わせて、列単位の平均を取ります。
# アヤメの種類をone-hotベクトル化
onehot = np.eye(int(np.max(data[:,1]))+1)[data[:,1].astype("int")]
# one-hotの0をNaNに置き換える
onehot[onehot==0] = np.nan
# 花弁の長さ×one-hot
length_oh = data[:,0].reshape(-1,1) * onehot
# 列単位の平均(Nanを除外して平均)
group_mean = np.nanmean(length_oh, axis=0)
print(group_mean)
グループの数が多いとちょっとメモリ食うかもしれません。one-hotベクトルをそのまま平均を取ってしまうと0の影響を受けてしまうので事前にNaNに置き換えます。np.nanmeanはNaNを除外して計算する関数です。標準偏差を取りたい場合はnanstdとします。
結果は以下の通りです。
[0.244 1.326 2.026]
NaNでもなんでもいいので、one-hotベクトル使って集計するときは必ず0を除外することを忘れないようにしてください。
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー