Matplotlib
には、簡単にヒストグラムを描く便利な機能plt.hist()
が備わっています。
とはいっても、plt.hist()
は初心者の方には使い方が少し難しいかもしれません。
そこで、今回は…
Matplotlib
でヒストグラムを作るにはどうしたらいいの?- データ区間の変更や見た目の設定方法がわからない…。
という方のために、
Matplotlib
でヒストグラムを作成する機能plt.hist()
の使い方plt.hist()
を使ってデータ区間の設定やヒストグラムの見た目を設定する方法
について紹介します。
plt.hist()
をマスターすれば、エクセルよりも簡単にヒストグラムが作れるようになります!
- plt.hist()の超基本|ヒストグラム作成入門
- ヒストグラムの集計結果の確認方法
- 確率密度関数・累積分布関数の出力:density, cumulative
- 対数軸のヒストグラム作成
- ヒストグラムの見た目変更
- 複数ヒストグラムの表示
- おわりに:Matplotlib関連記事の紹介
plt.hist()の超基本|ヒストグラム作成入門
ヒストグラムは簡単に言うと、データの分布を表現したり、集計したりするために使用するグラフの一つです。
データをある区間ごとに集計して、各区間内のデータの個数を棒グラフのように出力します。
縦軸、横軸は次のようになります。
- 横軸(x軸):データの区間(階級)
- 縦軸(y軸):区間に含まれるデータの個数(度数)
サンプルデータを使用して、簡単なヒストグラムを作成してみます。
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
#ヒストグラム用データを準備
x = np.random.randn(10000)
このサンプルデータは、正規分布に従った乱数を10,000個生成したものです。
- 【参考】
NumPy
で乱数を生成する方法は、次の記事を参考にしてください。
Matplotlib
のデフォルト設定でヒストグラムを作成するには、
plt.hist(x)
でプロットを生成plt.show()
でグラフを表示
を実行します。
plt.hist(x)
plt.show()
デフォルトでは、データの最小値から最大値までを10区間に区切ったヒストグラムが作成されます。
まずは、基本的なヒストグラムの作成/設定方法として
- データの区間(階級)の指定方法
- データの使用範囲(最大値・最小値)の指定方法
を紹介していきます。
この記事では基本的にplt.hist()
で解説しますが、ax.hist()
でも挙動はほぼ同じです。
オブジェクト指向の方はax.hist()
で実行してください。
- 【参考】オブジェクト指向のグラフ描画については、こちらの記事を参考にしてください。
plt.hist()の基本的な引数
plt.hist()
の基本引数は次の通りです。
引数 | 設定内容 | 設定値の例 |
---|---|---|
x (必須) |
ヒストグラムを作成するデータ | リスト やndarray など |
bins |
データ区間(階級)の作成方法指定 | int :区間の数リストなど :ユーザー指定の区間を直接入力文字列 :区間作成法則などを指定 |
range |
使用するデータの最大値・最小値指定 | タプルやリストなど:(min, max) 形式 |
必須引数はデータx
のみですが、
- データ区間を設定する引数
bins
- 使用するデータ範囲を指定する引数
range
も基本的な引数として紹介します。
データ区間(階級)の指定方法:bins
引数bins
を設定することで、データ区間の指定方法を変更することができます。
bins
の指定方法は次の3つがあります。
数値
で区間の個数を指定[リスト]など
で、区間を直接指定"文字列"
で既定の区間作成方法を指定
それぞれの指定方法を紹介していきます。
1. 数値
で区間の個数を指定
デフォルトでは、データの最小値から最大値を10個の区間に区切るように設定されています。
bins = 数値
とすることで、データ区間数を変更できます。
例として、100区間に変更してみましょう。
plt.hist(x, bins=100)
plt.show()
データ区間が細かくなり、滑らかなヒストグラムになりました。
2. [リスト]
などで、区間を直接指定
自分で準備したデータ区間がある場合には、リスト
やndarray
などの形式でbins
に渡します。
bins = [自分で準備したデータ区間]
例として、-4から4までを0.5ずつ分割した区間を指定してみます。
bins = [-4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0,
0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4]
plt.hist(x, bins=bins)
plt.show()
この例ではbins=17
を指定した場合と同じ結果なので、あまり意味がなさそうに見えますが…。
- 他のデータとデータ区間を揃える場合
- 集計区間として対数を使用したい場合
のように、データ区間を固定する必要がある場合に便利な指定方法です。
3. "文字列"
で既定の区間作成方法を指定
NumPy
で用意されている区間生成方法を指定できます。
例えば、"auto"
を指定するとデータに応じて適切なデータ区間を自動で設定してくれます。
plt.hist(x, bins="auto")
plt.show()
この他にも既定の指定方法があるので、興味のある方はNumPy
のドキュメントを参照してください。
データの使用範囲を指定:range
ヒストグラムに使用するデータの範囲を指定するには、引数range
を指定します。
range = (最小値, 最大値)
デフォルトでは、データx
の最小値、最大値が使用されています。
- デフォルト:
range = (x.min(), x.max())
例として、データの使用範囲を(0, 5)
に指定してみます。
plt.hist(x, bins=100, range=(0,5))
plt.show()
データの使用範囲の指定は、外れ値を使用したくないときに便利ですね。
ヒストグラムの集計結果の確認方法
作成されたヒストグラムの集計値は、plt.hist()
の戻り値で取得することができます。
次のように3つの変数名で戻り値を受け取ることが多いです。
n, bins, patches = plt.hist(x)
各戻り値の内容は次の通りです。
変数名 | 戻り値の内容 |
---|---|
n |
各区間のデータの個数(度数) |
bins |
データ区間の境界値のリスト(階級) |
patches |
ヒストグラムの棒を表すオブジェクトのリスト |
例として、サンプルデータでbins=4
, range=(-4,4)
を指定した場合の戻り値を確認してみましょう。
n, bins, patches = plt.hist(x, bins=4, range=(-4, 4))
plt.show()
このときの戻り値の中身は次の通りです。
print(f"n = {n}")
# n = [ 219. 4834. 4719. 228.]
print(f"bins = {bins}")
# bins = [-4. -2. 0. 2. 4.]
print(f"patches = {patches}")
# patches = <a list of 4 Patch objects>
bins
に各区間の境界値、n
に各区間内のデータの個数が集計されていますね。
bins
とn
の関係を図にすると次のようになっています。
bins
は境界の値なので上端下端がある分、要素の数がn
より1つ多い点に注意しましょう。
確率密度関数・累積分布関数の出力:density, cumulative
引数density
, cumulative
をTrue/False
で指定して、集計方法を変更できます。
density = True
:相対度数で集計cumulative = True
:累積値で集計
これらを組み合わせることで、次の4つのパターンのグラフを作成できます。
density = False (デフォルト) |
density = True |
|
---|---|---|
cumulative = False (デフォルト) |
ヒストグラム(度数分布) | 確率密度関数(相対度数) |
cumulative = True |
累積ヒストグラム(累積度数分布) | 累積分布関数(累積相対度数) |
各グラフを出力してみましょう。
plt.figure(tight_layout=True)
# ヒストグラム(度数分布)
plt.subplot(221)
plt.hist(x, bins=100)
plt.title("Histogram")
# 確率密度関数(相対度数)
plt.subplot(222)
plt.hist(x, bins=100, density=True)
plt.title("Probability density function")
# 累積ヒストグラム(累積度数分布)
plt.subplot(223)
plt.hist(x, bins=100, cumulative=True)
plt.title("Cumulative histogram")
# 累積分布関数(累積相対度数)
plt.subplot(224)
plt.hist(x, bins=100, cumulative=True, density=True)
plt.title("Cumulative density function")
plt.show()
サンプルコードでは、plt.figure()
でサブプロットのレイアウトを自動調整しています。
plt.figure()
やplt.subplot()
の詳しい使い方は、次の記事を参考にしてください。
対数軸のヒストグラム作成
ヒストグラムの軸を対数に設定する方法を紹介します。
縦軸(度数)を対数にする場合は単に見た目の問題です。
一方、横軸を対数にする場合はデータ区間(階級)にして集計する必要があります。
縦軸を対数に設定:log
縦軸(度数)を対数にする場合は、次のどちらかの方法で設定します。
- 引数で指定:
log = True
または - 軸設定の関数で変更:
plt.yscale("log")
それぞれの例を見てみましょう。
plt.hist(x, bins=100, log=True)
plt.show()
plt.hist(x, bins=100)
plt.yscale("log")
plt.show()
どちらも同じ結果になります。
- 【参考】軸周りの設定については、次の記事で詳しく解説しています。
横軸を対数に設定:bins = np.logspace()
横軸を対数に設定するには、次の2つの手順を踏みます。
- データ区間(階級)を対数で設定|
bins = np.logspace(min, max, num)
- 横軸のスケールを対数に設定|
plt.xscale("log")
まずは次の対数正規分布のデータを、普通の軸でヒストグラムにしてみます。
y = np.random.lognormal(size=10000)
plt.hist(y, bins=50)
plt.show()
通常の軸だと、次のようなヒストグラムになります。
次に、データ区間を対数軸にしてヒストグラムを作成してみましょう。
# 対数でデータ区間を生成
bins = np.logspace(-2, 3, num=50)
# array([1.00000000e-02, 1.26485522e-02, 1.59985872e-02,…略])
plt.hist(y, bins=bins)
plt.xscale("log")
plt.show()
横軸が対数軸になっていて、データ区間も対数軸に対応するように設定されています。
ヒストグラムの見た目変更
ヒストグラムの見た目を変更する方法を
- ヒストグラム全体のスタイル変更
- 枠線の見た目設定
- 棒の見た目設定
- 棒の表示位置調整
の順に解説していきます。
ヒストグラムのスタイル変更:histtype
ヒストグラムのスタイルは引数histtype
で変更することができます。
引数 | 指定値 | 設定内容 |
---|---|---|
histtype |
'bar' (デフォルト) |
棒グラフを並べたヒストグラム |
'step' |
外枠だけのヒストグラム (塗りつぶし無し) |
|
'stepfilled' |
外枠だけのヒストグラム (塗りつぶし有り) |
|
'barstacked' |
複数のヒストグラムを積み上げる |
'bar'
, 'step'
, 'stepfilled'
のスタイルを比較してみます。
plt.figure(figsize=(9, 3), tight_layout=True)
# histtype="bar"
plt.subplot(131)
plt.title('histtype="bar"')
plt.hist(x, bins=30, histtype="bar", edgecolor="black")
# histtype="step"
plt.subplot(132)
plt.title('histtype="step"')
plt.hist(x, bins=30, histtype="step", edgecolor="black")
# histtype="stepfilled"
plt.subplot(133)
plt.title('histtype="stepfilled"')
plt.hist(x, bins=30, histtype="stepfilled", edgecolor="black")
plt.show()
デフォルトではヒストグラムの枠線が非表示なので、比較のためにedgecolor='black'
で表示させています。
また、histtype='barstacked'
は複数系列のヒストグラムを積み上げで表示します。
複数系列のヒストグラムは、他にも設定があるので後ほど紹介します。
枠線の見た目変更
デフォルトではヒストグラム各要素の枠線は表示されませんが、次の引数で表示/設定ができます。
キーワード | 設定内容 | 設定値の例 |
---|---|---|
edgecolor |
枠線の色 | 色の名前など ex) gray , red , blue |
linewidth |
線の太さ | 数値 ptで指定 |
linestyle |
線のスタイル | - , -- , -. , : , で指定 |
枠線の色とスタイルを設定してみましょう。
plt.hist(x, bins=20, color="lightblue", edgecolor="black", linestyle="--")
plt.show()
Matplotlib
での色の設定方法には、次の記事で詳しく解説しています。
棒の見た目変更
ヒストグラム各要素の棒の見た目は、次の引数で設定することができます。
キーワード | 設定内容 | 設定値の例 |
---|---|---|
rwidth |
棒の太さ | データ区間に対する比:0~1 |
color |
棒の色 | 色の名前など ex) gray , red , blue |
alpha |
棒の透明度 | 0 (完全透明)~1 (不透明) |
hatch |
棒の柄 | '/' , '\', '|' , '-' , '+' , 'x' , 'o' , 'O' , '.' , '*' で指定 |
ヒストグラムの棒の太さを変更してみます。
plt.hist(x, bins=20, rwidth = 0.8)
plt.show()
次に色を設定してみます。
plt.hist(x, bins=20, color="green")
plt.show()
棒の設定は、棒グラフの設定と似ている部分があるので、次の記事も参考にしてください。
棒の表示位置調整:align
デフォルトでは、各棒は
データ区間の真ん中の値=棒の真ん中の座標
となるように配置されますが、引数align
で各棒の配置位置を調整できます。
引数 | 指定値 | 棒の真ん中の座標 = |
---|---|---|
align |
'mid' (デフォルト) |
データ区間の真ん中の値 |
'left' |
データ区間の左端の値 | |
'right' |
データ区間の右端の値 |
'mid',
'left',
'right'
それぞれを指定したヒストグラムを比較してみましょう。
fig, axes = plt.subplots(3, 1, tight_layout=True)
alins = ["mid", "left", "right"]
for i, alin in enumerate(alins):
axes[i].hist(x, bins=[-4, -2, 0, 2, 4], align=alin, edgecolor="black", color="lightblue")
axes[i].set_title(alin)
axes[i].set_xticks([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5])
plt.show()
ヒストグラムの各棒の中央座標が、align
によって調整されていますね。
サンプルコードはスッキリ書くために、plt.subplots()
を使用してオブジェクト指向で作成ています。
- 【参考】
plt.subplots()
の詳しい使い方は次の記事で紹介しています。
複数ヒストグラムの表示
複数のヒストグラムを作成する場合は、
- 複数ヒストグラムを積み上げる場合
- 複数ヒストグラムを別々に集計する場合
で作成方法が異なります。
複数ヒストグラムの積み上げ
複数ヒストグラムを積み上げる場合には、
histtype="barstacked"
またはstacked=True
を指定します。
このときヒストグラムのデータは、リストやタプルなどでまとめて渡します。
x = (ヒストグラム1のデータ, ヒストグラム2のデータ)
2系列のヒストグラムを積み上げで作成してみましょう。
# 系列2のデータを用意
x2 = x+3
plt.hist((x, x2), bins=100, histtype="barstacked")
plt.show()
histtype="barstacked"
を使用すると、ヒストグラムのスタイルは棒グラフに固定されます。
stacked=True
を使用すれば、histtype
も一緒に変更できます。
plt.hist((x, x2), bins=100, stacked=True, histtype="step")
plt.show()
複数ヒストグラムを別々に集計
複数ヒストグラムを積み上げない場合、表示するだけであれば簡単です。
複数のヒストグラムのデータを、リストやタプルなどでまとめて渡します。
x = (ヒストグラム1のデータ, ヒストグラム2のデータ)
このとき、rwidth=1
を指定しておくと、棒の間の隙間がなく表示されます。
plt.hist((x, x2), bins=25, rwidth=1)
plt.show()
複数系列のヒストグラムを前後に重ねて表示したいと思った方もいると思います。
データ区間を統一しなくても良い場合は、plt.hist()
を2回実行すればOKです。
plt.hist(x , bins=11, alpha=0.8,edgecolor="gray")
plt.hist(x2, bins=11, alpha=0.8,edgecolor="gray")
plt.show()
しかし、これではデータ区間がずれていて、気持ち悪いですね。
複数ヒストグラムでデータ区間を統一する場合、事前にbins
を自作するのが簡単です。
x_new = np.concatenate([x,x2])
bins = np.linspace(x_new.min(), x_new.max(), num=26)
plt.hist(x , bins=bins, alpha=0.8,edgecolor="gray")
plt.hist(x2, bins=bins, alpha=0.8,edgecolor="gray")
plt.show()
凡例の表示
凡例を表示するためには、データにラベル名を設定します。
label = "laben_name"
凡例表示の関数plt.legend()
を実行すると、グラフに凡例が表示されるようになります。
x_new = np.concatenate([x,x2])
bins = np.linspace(x_new.min(), x_new.max(), num=26)
plt.hist(x , bins=bins, alpha=0.8,edgecolor="gray", label="data1")
plt.hist(x2, bins=bins, alpha=0.8,edgecolor="gray", label="data2")
plt.legend()
plt.show()
- 【参考】凡例の作成方法は次の記事で詳しく解説しています。
おわりに:Matplotlib関連記事の紹介
今回は、Matplotlib
のヒストグラムの作成方法を解説しました。
plt.hist()
を使用すれば簡単にヒストグラムが作成する方法- 引数でデータ区間の設定やヒストグラムの見た目を設定する方法
について解説しました。
plt.hist()
の使い方を覚えれば、Excelよりも簡単にヒストグラムが作れそうですね。
Matplotlib
マスターを目指す皆さんへの次のおススメコンテンツはこちらです!
Twitter@YutaKaでは、ほぼ毎日pythonに関する情報を発信しています。
気楽にツイートしているので、気軽にフォローしてください!