Pythonでヒストグラムを描く

Pythonでヒストグラムを描く

こんにちは。マスジュンです。

今回はヒストグラム(度数分布)のプロットをseabornを中心に行っていきます。このプロセスってかなり重要です。たまに、購買回数のデータを全く加工せず、いきなり重回帰分析とか行っている分析とか見かけたりするときは、「え?ちょ、マジ?」って思うこともしばしば。いずれ、その影響に関する記事を書こうとは思いますが、その前に今日はその分布の確認方法であるヒストグラムの作図を行っていきます。

では、はじめて行きましょう。

パッケージ

今回は基本的にseabornを用いて描画していきます。先ずは必要なパッケージの呼び出しと、seabornのスタイルを設定しておきます。

In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

sns.set_style('darkgrid') #seaborneのグラフレイアウト

データ

お馴染みテストデータであるirisで試していきます。

In [2]:
import seaborn as sns
iris=sns.load_dataset("iris")
iris.head()
Out[2]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

準備はここまで。では、グラフを描いていきましょう。

ヒストグラム

ヒストグラム

先ずは、シンプルにヒストグラムを作図。seabornはdistplotでヒストグラムを描画してくれます。今回は10区分で描いてみます。

In [3]:
sns.distplot(iris.sepal_length, hist=True, kde=False, rug=False, bins=10)
plt.title('histogram', size=20)
plt.ylabel('freq')
plt.xlabel('sepal_length')
plt.show()

区分の間に隙間がある方が見やすくて好きなんですが、ヒストグラムの本来の形はこっちなんですよね。

カーネル密度推定

kde=Trueにすれば、カーネル密度推定(KDE)の結果を描いてくれます。KDEは**いまあるデータから、全体の分布の推定**を行ってくれます。

In [4]:
sns.distplot(iris.sepal_length, hist=False, kde=True, rug=False, bins=10) #kdeでカーネル密度を計算
plt.title('KDE',size=20)
plt.xlabel('sepal_length')
plt.ylabel('prob')
plt.show()

確率分布なので、縦のメモリが確率になりました。まー、正規分布と見なせなくもないですが、幅を狭くしてKDEを行ってみます。

In [5]:
sns.kdeplot(iris.sepal_length, bw=0.1, label="bw: 0.1")
sns.kdeplot(iris.sepal_length, bw=0.4, label="bw: 0.4")
plt.title('KDE',size=20)
plt.xlabel('sepal_length')
plt.ylabel('prob')
plt.show()

推定する幅を長く取れば、滑らかにフィットしてくれます。正規分布とみなしても良さそうですが、混合分布の感じも否めないですね。

各グループのヒストグラム

irisデータは品種の項目があるので、品種ごとにヒストグラムを描写してみます。

In [6]:
grid = sns.FacetGrid(iris, col="species", hue="species", col_wrap=3, size=4)
grid.map(sns.distplot, "petal_length")
plt.subplots_adjust(top=0.8)
grid.fig.suptitle("histogram by species",size=20)
Out[6]:
Text(0.5,0.98,'histogram by species')

各品種が正規分布っぽいことが確認できますね。あと、ベースの長さの差も見て取れます。

重ねてヒストグラム

ベースの長さの差を比較して見るために、3つの品種のヒストグラムを重ねて描いてみます。

In [7]:
sns.distplot(iris[iris["species"]=="setosa"].sepal_length,kde=True,rug=True,label="setosa")
sns.distplot(iris[iris["species"]=="versicolor"].sepal_length,kde=True,rug=True,label="versicolor")
sns.distplot(iris[iris["species"]=="virginica"].sepal_length,kde=True,rug=True,label="virginica")
plt.title('histogram by species',size=20)
plt.xlabel('sepal_length')
plt.ylabel('prob')
plt.legend() #実行させないと凡例が出ない。
plt.show()

比較しやすくなりましたね。たまに、これでもか!ってぐらいの数のグラフを重ねて表示する人いますよね(笑)。もうどれがどれだかわからない感じに(笑)

一気に分布を確認する

seabornではないですが、pandasのplotを使うと各変数のヒストグラムを一気に出すことができます。

In [8]:
iris.plot(kind='kde',subplots=True,layout=(2,2),alpha=0.5,figsize=(10,5),title='kde',
          legend='reverse')
plt.show()

探索的に分析を行う際などは、一気に全変数の分布を出力させたりします。データのチェックにもなりますし。

2変数ヒストグラム

joinplotと使っても、ヒストグラムを出力できます。

In [9]:
sns.jointplot(x='sepal_width', y='petal_length', data=iris)
plt.show()

カーネル密度推定にすれば、2次元確率分布の形で確認できます。

In [10]:
fig = sns.jointplot(x="sepal_width", y="petal_length", data=iris, kind="kde")
fig.plot_joint(plt.scatter, c="c", s=30, linewidth=1, marker="+")
fig.ax_joint.collections[0].set_alpha(0)
fig.set_axis_labels("sepal_width", "petal_length")
plt.show()

このjointplotは綺麗でカッコイイんですけど、自分はあまり使わないです。というか、使い所がわからない。。。

Pairプロット

pairplotでもヒストグラムを確認できます。joinplotより探索的で、よく使っています。結構、ビジネスのデータ分析って探索的で泥臭い作業が多いので。

In [11]:
g = sns.pairplot(iris, hue = "species",diag_kind="kde")
plt.subplots_adjust(top=0.9)
plt.suptitle('Iris Pair Plot',size=20)
plt.show()

いや、キレイですね。引数を使えば、変数が多い場合は数を絞ったり、散布図に回帰直線を引いたり、グラフの書式を変えることも可能です。

In [12]:
g = sns.pairplot(iris, hue = "species",diag_kind="kde", kind='reg',
                plot_kws={'scatter_kws': {'alpha': 0.5}},
                vars=["sepal_width", "sepal_length"])

plt.suptitle('Iris Pair Plot',size=20)
plt.subplots_adjust(top=0.9)
plt.show()
In [13]:
g = sns.pairplot(iris, hue = "species", kind='reg',
                plot_kws={'scatter_kws': {'alpha': 0.5}},
                x_vars=["sepal_width", "sepal_length"],
                y_vars=["petal_width","petal_length"])
plt.subplots_adjust(top=0.9)
plt.suptitle('Iris Pair Plot',size=20)
plt.show()

対角成分が同じにならないから、ヒストグラム出力されないや(笑)。

まとめ

主にseabornを使って分布確認のグラフ作成をしてきました。seabornはデフォルトでキレイなグラフを作成してくれるので、重宝しています。matplotとも相性が良いので、今のところはseaborn派です。PlotlyがAPI無しで色々できるようになったら、浮気してしまいそうですが。。。

 

Pythonカテゴリの最新記事