こしあん
2018-08-28

Numpyのみでグループ別に集計し平均を出す方法(for文、Pandasなし)


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を除外することを忘れないようにしてください。

Related Posts

PandasのDataFrameでグループ別にサンプルをN個抜き出す方法... 「PandasでGroupbyでグルーピングしたはいんだけど、そこからグループ別にサンプルを1個、2個…と抜き出す、SQLでよくやるやつってどうやるんだっけ?」ということが気になったので、調べました。ちゃんとした方法があります。 例題 今、中国地方と四国地方の県と面積をDataFrameにして...
統計学や機械学習で使われる分散共分散行列、相関行列とグラム行列の関係... TensorFlowなど分散共分散行列の計算関数が用意されていない場合は、分散共分散行列や相関行列を計算する際に自分で関数を定義しなければいけません。そこでグラム行列から、分散共分散行列、相関行列と派生させて計算する方法を理論を中心に見ていきます。 きっかけは主成分分析を使ったPCA Color...
pandasでグループ別に統計量やヒストグラムを表示する方法... 初投稿です。この記事では、pandasでグループ別に基本統計量(describe)をする方法を紹介します。 テストデータ 以下のようなデータを想定します。ある学校の3つのクラスでテストをしてみました。 A組は40人、平均点は60点、標準偏差は10(分布は正規分布に従うものとする) B組は...
Pandasで複数の列を値をもとに、新しい列を任意の関数で定義する方法... Pandasで、「列A(文字列)と列B(数字)」を文字列として結合し、新しい列を定義するという操作をしたかったのですが、思ったよりも情報がなくハマったので解説していきたいと思います。 サンプルデータ 次のようなデータを定義しました。コミケのサークルスペースのデータを模したものです。 impo...
Tags:

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です