この記事で行うこと
matplotlibで、ヒストグラムの縦軸を
- 度数(matplotlibのデフォルト)
- 相対度数
- 相対度数密度
にして描画します。
参考ページ(感謝します)
matplotlib.histのnormedが変
matplotlib:histgram normedの挙動
統計学② pythonを使って、確率密度関数(正規分布、標準正規分布)を覚えちゃう!
用語の整理
計算式は、
- 度数密度 = 度数 / 階級幅
- 相対度数密度 = 相対度数 / 階級幅
らしいです。
下記のPythonコードで実験したところ、hist関数で「density=True」を指定すると、縦軸が相対度数密度になるようです。
hist関数にはnormedオプション(非推奨)もありますが、これのバグを取り除いたものがdensityオプションだそうです。
ソースコード(Jupyter Notebook)と描画結果
3つのヒストグラムを描画します。
データ件数は10000件で、平均値50、標準偏差10の正規乱数にしました。
#%% md
#%%
import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt
#%%
# データ作成
μ = 50
σ = 10
data = [ np.random.normal(μ, σ) for i in range(10000) ]
#%%
# 階級数
num_bins = 20
# 階級幅
bin_width = (max(data) - min(data)) / num_bins
print(f"階級幅 = 約{bin_width}")
# グラフ描画
fig = plt.figure(figsize=(8, 24))
# (1) 縦軸を度数にしたヒストグラム
ax1 = fig.add_subplot(311)
ax1.title.set_text("(1) frequency")
ax1.grid(True)
ax1.hist(data, bins=num_bins)
# (2) 縦軸を相対度数にしたヒストグラム
ax2 = fig.add_subplot(312)
ax2.title.set_text("(2) relative frequency")
ax2.grid(True)
ax2.set_xlim(ax1.get_xlim())
weights = np.ones_like(data) / len(data)
ax2.hist(data, bins=num_bins, weights=weights)
# (3) 縦軸を相対度数密度にしたヒストグラム(青) & 正規分布の確率密度関数(赤)
ax3 = fig.add_subplot(313)
ax3.title.set_text("(3) density")
ax3.grid(True)
ax3.set_xlim(ax1.get_xlim())
ax3.hist(data, bins=num_bins, density=True, color="blue", alpha=0.5)
x = np.arange(0, 100, 1)
y = norm.pdf(x, μ, σ)
ax3.fill_between(x, y, color="red", alpha=0.5)
ax3.plot(x, y, 'k', linewidth=3, color="red", alpha=0.5)
コードを実行すると、「階級幅 = 約3.718313197105561」と表示され、以下のヒストグラムが描画されました。
3つのヒストグラムはそれぞれ、(1)縦軸=度数、(2)縦軸=相対度数、(3)は縦軸=相対度数密度のヒストグラム(青)に正規分布の確率密度関数(赤)を重ねて表示しています。
「density=True」のヒストグラムと確率密度関数が重なっていますから、「density=True」にするとヒストグラム全体の面積が1になるようです。
「density=True」で縦軸が相対度数密度になっているか、計算式からざっくり検証
検証にヒストグラムの一番高い柱を使います。
相対度数
(2)の一番高い柱は0.14と0.15の間の値です。
階級幅
コードを実行した時、約3.7と表示されました。
相対度数密度
相対度数 / 階級幅 = 0.145 / 3.7 ≒ 0.039
(3)の一番高い柱と合っているように見えます。
(検証終わり)
相対度数のヒストグラムで、柱の高さの合計が1.0になっているか検証
上記ヒストグラムを読み取って合計するのも大変なので、Pythonコードの階級数(num_bins変数)を1にして再実行してみます。
(2)の唯一の柱の高さが1.0になりました。
また、10000件のデータを使いましたので、(1)の唯一の柱の高さも10000になっています。
(3)の「density=True」のヒストグラム(青)も、確率密度関数(赤)の面積と同じように見えます(面積=1)。
(検証終わり)