以下に正規分布の散布図と楕円(3σ),最小二乗法のプロットを示します.楕円を描くメソッド confidence_ellipse() は,Plot a confidence ellipse of a two-dimensional dataset 記載されているものを使いました.
# -*- coding:utf-8 -*- import numpy as np from numpy.random import multivariate_normal as normal import matplotlib.pyplot as plt from matplotlib.patches import Ellipse import matplotlib.transforms as transforms # ------------------------------------------------------------------------- # https://matplotlib.org/devdocs/gallery/statistics/confidence_ellipse.html # 入力引数 # x, y: 入力データ 配列, shape (n, ) # ax: matplotlib.axes.Axes # n_std: float 標準偏差の n_std 倍のプロットを作成 # **kwargs: `~matplotlib.patches.Ellipse` が引き継ぐ # 戻り値 # matplotlib.patches.Ellipse # ------------------------------------------------------------------------- def confidence_ellipse(x, y, ax, n_std=3.0, facecolor='none', **kwargs): ''' 分布の楕円を作成する. ''' if x.size != y.size: raise ValueError("x and y must be the same size") cov = np.cov(x, y) mean_x, mean_y = np.mean(x), np.mean(y) pearson = cov[0, 1]/np.sqrt(cov[0, 0] * cov[1, 1]) ell_radius_x = np.sqrt(1 + pearson) ell_radius_y = np.sqrt(1 - pearson) ellipse = Ellipse((0.0, 0.0), width=ell_radius_x*2, height=ell_radius_y*2, facecolor=facecolor, **kwargs) scale_x = np.sqrt(cov[0, 0]) * n_std scale_y = np.sqrt(cov[1, 1]) * n_std transf = transforms.Affine2D() \ .rotate_deg(45) \ .scale(scale_x, scale_y) \ .translate(mean_x, mean_y) ellipse.set_transform(transf + ax.transData) return ax.add_patch(ellipse) if __name__ == "__main__": # --- プロットデータの作成 --- xlim, ylim = [-10, 10], [-10, 10] mean = [-1, -2] cov = [[8, -3], [-3, 4]] x, y = normal(mean, cov, 1000).T conf = np.polyfit(x,y,1) xls = np.linspace(xlim[0], xlim[1], 256) yls = conf[1]+conf[0]*xls # --- プロットの作成 OO-API --- fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.set_title("2D normal distribution", fontsize=20, fontname='serif') ax.set_xlabel("x data", fontsize=20, fontname='serif') ax.set_ylabel("y data", fontsize=20, fontname='serif') ax.tick_params(axis='both', length=10, which='major', labelsize=16) ax.tick_params(axis='both', length=5, which='minor') ax.set_xlim(xlim) ax.set_ylim(ylim) ax.minorticks_on() ax.grid(b=True, which='major', axis='both') ax.scatter(x, y, s=5, marker='o', edgecolor="b", label='scatter data') confidence_ellipse(x, y, ax, n_std=3, label=r'$3\sigma$', edgecolor='red') ax.plot(xls, yls, 'g-', label='Least squares') # ----- プロットの表示 ----- ax.legend() plt.show() # ----- プロットファイルの作成 ----- fig.savefig('normal_dist.pdf', orientation='portrait') fig.savefig('normal_dist.svg', orientation='portrait') fig.clf()