19
14

More than 3 years have passed since last update.

matplotlibでヒストグラムの縦軸を相対度数(柱の高さの合計=1)や相対度数密度(ヒストグラム全体の面積=1)にする

Last updated at Posted at 2019-11-05

この記事で行うこと

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になるようです。

1.png

「density=True」で縦軸が相対度数密度になっているか、計算式からざっくり検証

検証にヒストグラムの一番高い柱を使います。

相対度数

(2)の一番高い柱は0.14と0.15の間の値です。

階級幅

コードを実行した時、約3.7と表示されました。

相対度数密度

相対度数 / 階級幅 = 0.145 / 3.7 ≒ 0.039
(3)の一番高い柱と合っているように見えます。
(検証終わり)

相対度数のヒストグラムで、柱の高さの合計が1.0になっているか検証

上記ヒストグラムを読み取って合計するのも大変なので、Pythonコードの階級数(num_bins変数)を1にして再実行してみます。

2.png

(2)の唯一の柱の高さが1.0になりました。
また、10000件のデータを使いましたので、(1)の唯一の柱の高さも10000になっています。
(3)の「density=True」のヒストグラム(青)も、確率密度関数(赤)の面積と同じように見えます(面積=1)。
(検証終わり)

19
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
14