はじめに
Histgramは、numpyで計算してからplotする方法と、matplotlibで直接Plotする方法があります。(Matplotlibでも内部でnumpyを用いて計算している。)
matplotlibで直接Plotを行うには下記の1が参考になります。 ここでは、1の記事に従いnumpyで計算を行いその後Plotを行った覚えです。
ここでは、度数分布、相対度数分布、相対度数密度の計算とPlotを示します。
参考
ヒストグラムの用語
階級:度数を集計するための 1つ1つ区間
階級数 : 階級の数
階級幅 : 区間の大きさを階級の幅
階級値 : その階級を代表する値(階級の真ん中の値)
度数 (Frequency)
相対度数 (Relative Frequency)
-> 相対度数 = 度数 / 度数の合計値
相対度数密度 (Density = relative frequency density)
-> 相対度数密度 = 相対度数 / 階級幅
度数密度 (frequency density)
-> 度数密度 = 度数 / 階級幅
度数分布、相対度数分布、相対度数密度
import matplotlib.pyplot as plt
import numpy as np
# dataの作成
mu = 50
sg = 10
data = np.array([ np.random.normal(mu, sg) for i in range(10000) ])
print(f'Data length: {data.shape}, {len(data)}')
#>>>Data length: (10000,), 10000
plt.figure(figsize=(12, 6))
plt.subplot(1,2,1)
plt.plot(data)
plt.grid()
plt.subplot(1,2,2)
plt.plot(data.cumsum())
plt.title("cumsum")
plt.grid()
度数分布
# Frequency example
print('Frequency example')
# Bins (階級数)
num_bins = 100
# Bins width (階級幅)
bin_width = (max(data) - min(data)) / num_bins
print(f"Bin width: {bin_width:.3f}")
hist, bins = np.histogram(data, bins=num_bins)
print(f'Bins length:{len(bins)}')
# binsの長さに注意 帰ってくるbinsの長さは指定したnum_bins+1
print(f'Histgram length: {len(hist)}')
print(f'Max cumsum: {hist.cumsum().max():.2f}')
print(f'Area: {np.sum(bin_width*hist):.2f}')
plt.figure(figsize=(12, 6))
plt.subplot(1,2,1)
plt.title("histgram")
plt.plot(bins[:-1],hist)
plt.grid()
plt.subplot(1,2,2)
plt.plot(bins[:-1],hist.cumsum())
plt.title("cumsum")
plt.grid()
Frequency example
Bin width: 0.766
Bins length:101
Histgram length: 100
Max cumsum: 10000.00
Area: 7662.08
相対度数分布
# Relative Frequency example
print('Relative Frequency example')
# Bins
num_bins = 100
# Bins width
bin_width = (max(data) - min(data)) / num_bins
print(f"Bin width: {bin_width:.3f}")
# weightsを指定することで各階級の重み付けを行う
weights = np.ones_like(data) / len(data)
print(f'weight length:{len(weights)}')
hist, bins = np.histogram(data, bins=num_bins, weights=weights)
print(f'bins length:{len(bins)}')
print(f'histgram length: {len(hist)}')
print(f'Max cumsum: {hist.cumsum().max():.2f}')
print(f'Area: {np.sum(bin_width*hist):.2f}')
plt.figure(figsize=(12, 6))
plt.subplot(1,2,1)
plt.title("histgram")
plt.plot(bins[:-1],hist)
plt.grid()
plt.subplot(1,2,2)
plt.plot(bins[:-1],hist.cumsum())
plt.title("cumsum")
plt.grid()
# Note:
# 度数分布を求めて、度数累積和の最大値で規格化しても同じ
# hist, bins = np.histogram(data, bins=num_bins)
# plt.figure(figsize=(12, 6))
# plt.subplot(1,2,1)
# plt.title("histgram")
# plt.plot(bins[:-1],hist/(max(hist.cumsum())))
# plt.grid()
# plt.subplot(1,2,2)
# plt.plot(bins[:-1],hist.cumsum()/(max(hist.cumsum())))
# plt.title("cumsum")
# plt.grid()
Relative Frequency example
Bin width: 0.766
weight length:10000
bins length:101
histgram length: 100
Max cumsum: 1.00
Area: 0.77
累積和の最大値が1になっている。
# 累積和で50%の位置の階級値を求めたい場合
def getNearestValue(list, num):
"""
リストからある値に最も近い値を返却する関数
Args:
list (list or ndarray): 探索対象データ
num (float): 対象値
Returns:
float: 対象値に最も近い値
"""
# リスト要素と対象値の差分を計算し最小値のインデックスを取得
idx = np.abs(np.asarray(list) - num).argmin()
return idx
ind = getNearestValue(hist.cumsum(), 0.5)
print(f'Index :{ind}')
print(f'Bin : {bins[ind]}')
Index :52
Bin : 48.92290015560406
相対度数密度
# Density example
# Density (relative frequency density)
# -> Relative frequency density -> relative frequency / bin_width
print('Density (relative frequency density) example')
# Bins
num_bins = 100
# Bins width
bin_width = (max(data) - min(data)) / num_bins
print(f"Bin width : {bin_width:.3f}")
weights = np.ones_like(data) / len(data)
print(f'weight length : {len(weights)}')
hist, bins = np.histogram(data, bins=num_bins, weights=weights, density=True)
# weightsを指定しなくて同じ結果になる
# hist, bins = np.histogram(data, bins=num_bins, density=True)
print(f'bins length : {len(bins)}')
print(f'histgram length : {len(hist)}')
print(f'Max cumsum : {hist.cumsum().max():.2f}')
# density = True :ヒストグラム全体の面積が1になる。
print(f'Area: {np.sum(bin_width*hist):.2f}')
plt.figure(figsize=(12, 6))
plt.subplot(1,2,1)
plt.title("histgram")
plt.plot(bins[:-1],hist)
plt.grid()
plt.subplot(1,2,2)
plt.plot(bins[:-1],hist.cumsum())
plt.title("cumsum")
plt.grid()
Density (relative frequency density) example
Bin width : 0.766
weight length : 10000
bins length : 101
histgram length : 100
Max cumsum : 1.31
Area: 1.00
相対度数分布で範囲を変えた場合
# Relative Frequency example. Range change
print('Range change -Relative Frequency example- ')
# Bins
num_bins = 100
# Bins width
# bin_range =(min(data),max(data))
bin_range=(40,70)
bin_width = (max(bin_range) - min(bin_range)) / num_bins
print(f"Bin width: {bin_width:.3f}")
# weightsを指定することで各階級の重み付けを行う
weights = np.ones_like(data) / len(data)
print(f'weight length:{len(weights)}')
hist, bins = np.histogram(data, bins=num_bins, range=bin_range, weights=weights)
print(f'bins length : {len(bins)}')
print(f'histgram length : {len(hist)}')
print(f'Max cumsum : {hist.cumsum().max():.2f}')
print(f'Area : {np.sum(bin_width*hist):.2f}')
plt.figure(figsize=(12, 6))
plt.subplot(1,2,1)
plt.title("histgram")
plt.plot(bins[:-1],hist)
plt.grid()
plt.subplot(1,2,2)
plt.plot(bins[:-1],hist.cumsum())
plt.title("cumsum")
plt.grid()
Range change -Relative Frequency example-
Bin width: 0.300
weight length:10000
bins length:101
histgram length: 100
Max cumsum: 0.81
Area: 0.24