ヒストグラム

Matplotlibのヒストグラム

Python の Matplotlib のデフォルトのヒストグラムです:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(12345)
x = rng.random(1000)
plt.hist(x)
(array([ 94., 102., 109., 109., 112.,  94.,  97.,  99.,  85.,  99.]),
 array([4.37086824e-04, 1.00314361e-01, 2.00191635e-01, 3.00068909e-01,
        3.99946182e-01, 4.99823456e-01, 5.99700730e-01, 6.99578004e-01,
        7.99455278e-01, 8.99332552e-01, 9.99209826e-01]),
 )
ヒストグラム1

これは区切りが見にくいだけでなく、0.0 から 1.0 までが10等分されたように見えて、実は最小値 4.37086824e-04 から最大値 9.99209826e-01 までの区間が10等分されたもので、区切り位置は [0, 0.1, 0.2, …, 1] になっていません。

正しく描くには、次のようにビン(階級)の指定を明確にする必要があります:

plt.hist(x, color="lightgray", edgecolor="black", bins=np.arange(11)/10)
(array([ 94., 102., 109., 110., 111.,  94.,  97.,  99.,  85.,  99.]),
 array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]),
 )
ヒストグラム2

最初のヒストグラムでは左から3番目と4番目が同じ高さでしたが、正しく描いたヒストグラムでは3番目より4番目が高くなっています。

ここで np.arange(11) は 0 から 10 まで11個の整数の配列を意味します。これを10で割って、0 から 1 まで 0.1 刻みの配列にしています。このように与えると、10個の左閉区間 [0, 0.1)、[0.1, 0.2)、…、[0.9, 1.0] がビンになります。最後のビンだけ両側閉区間となることにご注意ください。

オプション density=True で縦軸が個数でなく密度になります。orientation="horizontal" で横向きになります。

左が閉じた区間になるのは R のデフォルトとは逆です。R ではオプション right=FALSE を付けると plt.hist() と同じになります。特に日本では区間は○○以上○○未満という形で表すのが普通なので、Python のデフォルトのほうが自然に思えます。

seabornのヒストグラム

seaborn では sns.histplot() を使います。デフォルトでは次のようになります:

import seaborn as sns

sns.histplot(x, bins=np.arange(11)/10)
ヒストグラム4

オプションは plt.hist() とだいたい同じですが、便利なオプションとして discrete=True があります。これは整数値のヒストグラムを描く場合に便利です:

a = np.floor(10 * x)
sns.histplot(a, discrete=True)
ヒストグラム5

なお、さいころの目の分布のようなもともと離散分布のものは、棒グラフのように棒と棒の間隔をあけて描くのが一般的だろうと思います:

sns.histplot(a, discrete=True, shrink=0.8)
ヒストグラム6

最後の2例を Matplotlib でするなら、それぞれ次のようになります:

plt.hist(a, bins=np.arange(min(a)-0.5, max(a)+1.5), edgecolor="black")
plt.hist(a, bins=np.arange(min(a)-0.5, max(a)+1.5), edgecolor="black", rwidth=0.8)