Yamamoto's Laboratory
基本事項
散布図

Matplotlib散布図 (scatter)

Matplotlib のモジュール Pyplot を使い散布図の作成方法を示します.

目次


基本事項

概要

散布図の例

シンプル

# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

# ----- 条件設定 -----
N = 1000                # サンプル数

# ----- 散布図用のデータの作成 -----
x0 = np.random.normal(0, 1, N)
y0 = np.random.normal(0, 1, N)-x0**2+7
x =  x0*np.cos(np.pi/4) + y0*np.sin(np.pi/4)
y = -x0*np.sin(np.pi/4) + y0*np.cos(np.pi/4)

# ----- プロット(散布図)作成 -----
plt.rcParams["font.size"] = 18
fig    = plt.figure()
fig.subplots_adjust(bottom=0.12)
ax = fig.add_subplot(1,1,1)
ax.set_xlabel("$x$", fontsize=24, fontname='serif')
ax.set_ylabel("$y$", fontsize=24, fontname='serif')
ax.tick_params(axis='both', length=10,  which='major')
ax.tick_params(axis='both', length=5,  which='minor')
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.minorticks_on()
ax.scatter(x, y, s=10, marker='x', edgecolor="b")

plt.show()
fig.savefig('scatter.pdf', orientation='portrait',
            transparent=False, bbox_inches=None,
            frameon=None)
fig.savefig('scatter.svg', orientation='portrait',
            transparent=False, bbox_inches=None,
            frameon=None)
fig.clf()

図1: シンプルな散布図

色付き

データの数が多くなると,データ点が重なり,分布がわかりにくくなります.このような場合,データ点の密度に応じた色付きの散布図にすると,分布の様子が分かりやすくなります.

# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde

# ----- 条件設定 -----
N = 10000                # サンプル数

# ----- 散布図用のデータの作成 -----
x0 = np.random.normal(0, 1, N)
y0 = np.random.normal(0, 1, N)-x0**2+7
x =  x0*np.cos(np.pi/4) + y0*np.sin(np.pi/4)
y = -x0*np.sin(np.pi/4) + y0*np.cos(np.pi/4)

# ----- データ点の密度の計算 ----
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)

# ----- 密度の高い点を最後にプロットするように密度でソート ----
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]

# ----- プロット(散布図)作成 -----
plt.rcParams["font.size"] = 18
fig    = plt.figure()
fig.subplots_adjust(bottom=0.12)
ax = fig.add_subplot(1,1,1)
ax.set_xlabel("$x$", fontsize=24, fontname='serif')
ax.set_ylabel("$y$", fontsize=24, fontname='serif')
ax.tick_params(axis='both', length=10,  which='major')
ax.tick_params(axis='both', length=5,  which='minor')
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.minorticks_on()
ax.scatter(x, y, c=z, marker='o', s=10, edgecolor='')

plt.show()
fig.savefig('scatter.pdf', orientation='portrait',
            transparent=False, bbox_inches=None,
            frameon=None)
fig.savefig('scatter.svg', orientation='portrait',
            transparent=False, bbox_inches=None,
            frameon=None)
fig.clf()

図2: 密度を色で表した散布図

正規分布と誤差楕円

正規分布とそれの誤差楕円

# -*- 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

    #  --- プロットの作成 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=1,
                       edgecolor='red', linewidth=2)
    confidence_ellipse(x, y, ax, n_std=2,
                       edgecolor='green', linewidth=2)
    confidence_ellipse(x, y, ax, n_std=3,
                       edgecolor='blue', linewidth=2)

    # ----- プロットの表示 -----
    plt.show()

    # ----- プロットファイルの作成 -----
    fig.savefig('normal_dist.pdf', orientation='portrait')
    fig.savefig('normal_dist.svg', orientation='portrait')

    fig.clf()

図3: 正規分布と誤差楕円

matplotlib の scatter のより深い情報

matplotlib.axes.Axes.scatter メソッドの引数は,以下のとおりです.

Axes.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None,
    vmin=None, vmax=None, alpha=None, linewidths=None, verts=None,
    edgecolors=None, **kwargs)
x, y : array_like, shape (n, )
入力の配列
s : scalar or array_like, shape (n, ), optional
サイズ [points^2]. デフォルト: rcParams['lines.markersize'] ** 2.
c : color, sequence, or sequence of color, optional, default: ‘b’
cは、単一のカラーフォーマット文字列,または長さ N のカラー指定のシーケンス,または kwargs (以下を参照) で指定された cmap と norm を使用してカラーにマッピングされる N個の数字のシーケンスです.カラーマップされる値の配列と区別がつかないので,c は単一の数値の RGB または RGBA シーケンスであってはならないことに注意.c は,行が RGB または RGBA の二次元配列ですが,すべての点で同じ色を指定する単一の行の場合も含めて,RGB または RGBA です.
marker : MarkerStyle, optional, default: ‘o’
さまざまなスタイルのマーカースキャッターサポートの詳細については,マーカーを参照してください.マーカーはクラスのインスタンスか,特定のマーカーのテキストの短縮形のどちらかです.
cmap : Colormap, optional, default: None
カラーマップインスタンスまたは登録された名前.cmap は,c が float の配列である場合にのみ使用されます.デフォルトの None の場合,rc image.cmap になります.
norm : Normalize, optional, default: None
Normalize インスタンスは,輝度データを 0, 1 にスケールするために使用されます.normは,c が float の配列である場合にのみ使用されます.Noneの場合,デフォルトの normalize() を使用します.
vmin, vmax : scalar, optional, default: None
vmin and vmax are used in conjunction with norm to normalize luminance data. If either are None, the min and max of the color array is used. Note if you pass a norm instance, your settings for vmin and vmax will be ignored.
alpha : scalar, optional, default: None
The alpha blending value, between 0 (transparent) and 1 (opaque)
linewidths : scalar or array_like, optional, default: None
If None, defaults to (lines.linewidth,).
verts : sequence of (x, y), optional
If marker is None, these vertices will be used to construct the marker. The center of the marker is located at (0,0) in normalized units. The overall marker is rescaled by s.
edgecolors : color or sequence of color, optional, default: None
If None, defaults to ‘face’
  • If ‘face’, the edge color will always be the same as the face color.
  • If it is ‘none’, the patch boundary will not be drawn.
  • For non-filled markers, the edgecolors kwarg is ignored and forced to ‘face’ internally.

ページ作成情報

参考資料

  1. scatter メソッドのマニュアルは,「matplotlib.axes.Axes.scatter — Matplotlib 2.0.2 documentation」です.
  2. 色付きの散布図の作成方法は,「python - How can I make a scatter plot colored by density in matplotlib? - Stack Overflow」を参考にしました.

更新履歴

2017年08月17日 新規作成


no counter