より良いエンジニアを目指して

1日1つ。良くなる!上手くなる!

pandas.DataFrame.groupbyした結果に対して、平均値でソートして箱ひげ図で表示したい

https://gist.github.com/rimever/90d1933ed481b044a94299f09c773685

pandas.DataFrameはgroupby関数で指定のカラムでグルーピングすることが出来るのですが、もどかしいことがありました。

  1. groupbyでグルーピング
  2. 箱ひげ図で表示してみる

というのは私がよくやるパターンなのですが、

f:id:rimever:20190108210702p:plain

このようになり、値の平均値でソートされて欲しいとモヤモヤすることがありました。

上記の図だと、3種類でいいのですが、これが多くなると見づらくなって来ます。

f:id:rimever:20181120214449p:plain

ここまで来ると、ややこしくなって来ます。

グループごとの平均値でソートした状態で並ぶといいのになと思って、毎回方法を探しては見つからず諦めていたのですが、やっとわかったのでその方法を紹介します。

from sklearn.datasets import load_iris
import pandas as pd
import matplotlib.pyplot as plt

iris_bunch = load_iris()
df = pd.DataFrame(iris_bunch.data, columns=iris_bunch.feature_names)
df['target'] = pd.Series(pd.Categorical.from_codes(iris_bunch.target, categories=iris_bunch.target_names))

group_label = 'target'
target_label = 'sepal width (cm)'

grouped = df.groupby(group_label)
agg = df.groupby(group_label).agg('mean').sort_values(target_label)

Y = []
labels = []
for index in agg.index.values:
    labels.append(index)
    Y.append(grouped.get_group(index)[target_label])
    
fig,ax = plt.subplots()
ax.boxplot(Y,labels=labels,vert=False)
plt.xlabel(target_label)
plt.ylabel(group_label)
plt.grid(True)
plt.show()

f:id:rimever:20190108212011p:plain

このようにソートされて表示されます。

agg関数で集約した値を用いて、グルーピングされた内容から必要な順に取得しています。

Gistにも挙げておきます。

DataFrameをGroupByした結果に対して、平均値でソートしたい場合 · GitHub