Matplotlibでグラフ
Matplotlib

Matplotlibによるグラフの基本

  • まずはインポート

    		import numpy as np
                    import matplotlib.pyplot as plt
    		# 軸の名前などに日本語が使用可能
                    plt.rcParams["font.family"] = "MS Gothic"
                  
  • グラフの基本

                    # 描画領域の確保
                    fig = plt.figure() 
    
                    # 軸の確保
                    # 1つだけのグラフであれば1,1,1で問題ない
                    # 複数のグラフを並べるときにこの数字は変わるが、それについては後述
                    ax = fig.add_subplot(1, 1, 1)
    
                    # 軸に折れ線グラフを描く
                    # 折れ線グラフはplotで、散布図 (線なし) はscatter
                    # ただしplotで散布図を描くこともできる
                    ax.plot(np.array([1, 4, 7]), np.array([2, 5, 1])) # (1,2),(4,5),(7,1)を繋ぐ折れ線グラフ
    
                    # グラフの描画
                    plt.show()
                  
  • 点を打つ

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
    
                    # markerオプションで指定した座標に点を打つことができる
                    # marker = "o" : 丸い点
                    # marker = "x" : バツ印
                    # marker = "^" : 三角形
                    ax.plot(np.array([1, 4, 7]), np.array([2, 5, 1]), marker = "o")
    
                    plt.show()
                  
  • 線種の変更

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # linestyleオプションで線種の変更ができる
                    # linestyle = "dashed" : 破線
                    # linestyle = "dotted" : 点線
                    # linestyle = "dashdot" : 一点鎖線
                    # linestyle = "none" : 線なし (markerと組み合わせると散布図ができる) 
                    ax.plot(x, np.sin(x), linestyle = "dashed")
    
                    plt.show()
                  
  • 色を変える

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # colorオプションで色の変更ができる (点の色も同時に変わる) 
                    # color = "red"
                    # color = "tab:red" : 柔らかめの赤
                    # color = "black"
                    ax.plot(x, np.sin(x), color = "tab:green")
    
                    plt.show()
                  
  • 軸に名前を付ける

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # ax.set_xlabelでx軸に名前が付く
                    ax.set_xlabel("x軸の名前")
                    # ax.set_ylabelでy軸に名前が付く
                    ax.set_ylabel("y軸の名前")
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • グラフに名前を付ける

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # ax.set_titleでグラフに名前が付く
                    ax.set_title("sin(x)のグラフ")
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • 軸の範囲を設定する

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # ax.set_xlimでx軸の範囲を変えられる
                    ax.set_xlim(0, np.pi)
                    # ax.set_ylimでy軸の範囲を変えられる
                    ax.set_ylim(-5, 5)
    
                    ax.plot(x, np.tan(x))
    
                    plt.show()
                  
  • 軸の数値を設定する

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # ax.set_xticks (ベクトル) でx軸の数値を好きな部分だけ表示できる
                    ax.set_xticks(np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]))
                    # ax.set_yticks (ベクトル) でy軸の数値を好きな部分だけ表示できる
                    ax.set_yticks(np.array([-1, -0.5, 0, 0.5, 1]))
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • 軸の数値を設定し、好きな表記にする

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    ax.set_xticks(np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]))
                    # ax.set_xticklabels (ベクトル) で、xticksで設定した数値の表示を変えることができる
                    # ax.set_xticksとax.set_xtickslabelsのベクトルの要素数は同じでなければならない
                    ax.set_xticklabels(np.array(["0", "π/2", "π", "3π/2", "2π"]))
    
                    ax.set_yticks(np.array([-1, 0, 1]))
                    # ax.set_yticklabels (ベクトル) で、yticksで設定した数値の表示を変えることができる
                    # ax.set_yticksとax.set_ytickslabelsのベクトルの要素数は同じでなければならない
                    ax.set_yticklabels(np.array(["ymin", "0", "ymax"]))
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • 目盛りに対してグリッドを付ける

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    ax.set_xticks(np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]))
                    ax.set_xticklabels(np.array(["0", "π/2", "π", "3π/2", "2π"]))
                    # ax.set_grid (axis = "x") で、x軸の目盛りに対してグリッドが付く。
                    ax.grid(axis = "x")
    
                    ax.set_yticks(np.array([-1, 0, 1]))
                    ax.set_yticklabels(np.array(["ymin", "0", "ymax"]))
                    # ax.set_grid (axis = "y") で、y軸の目盛りに対してグリッドが付く。
                    ax.grid(axis = "y", color="tab:red", linestyle = "dashed")
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • 数値の付かない小目盛りを付ける

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    ax.set_xticks(np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]))
                    ax.set_xticklabels(np.array(["0", "π/2", "π", "3π/2", "2π"]))
                    # minor = Trueオプションで小目盛りの設定になる
                    ax.set_xticks(np.array([np.pi/4, 3*np.pi/4, 5*np.pi/4, 7*np.pi/4]), minor = True)
    
                    ax.set_yticks(np.array([-1, 0, 1]))
                    ax.set_yticklabels(np.array(["ymin", "0", "ymax"]))
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • 小目盛りに対するグリッドを付ける

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    ax.set_xticks(np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]))
                    ax.set_xticklabels(np.array(["0", "π/2", "π", "3π/2", "2π"]))
                    ax.set_xticks(np.array([np.pi/4, 3*np.pi/4, 5*np.pi/4, 7*np.pi/4]), minor = True)
                    ax.grid(axis = "x")
                    # which = "minor"オプションで小目盛りに対するグリッドになる
                    ax.grid(axis = "x", which = "minor", linestyle = "dashed")
    
                    ax.set_yticks(np.array([-1, 0, 1]))
                    ax.set_yticklabels(np.array(["ymin", "0", "ymax"]))
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • x軸とy軸の長さと数値の割合を同じにする

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # ax.set_aspect(1)で、縦と横の数値の比率が同じになる
                    ax.set_aspect(1)
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • 文字列にLaTeXを用いる

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # 文字列の""の前にrを付けることによりLaTeXの表記が使えるようになる
                    # ax.set_x(y)label, ax.set_title, ax.set_x(y)ticklabels, label (後述) 等が対応する
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$\sin(x)$")
                    ax.set_title(r"$\sin(x)$のグラフ")
    
                    ax.set_xticks(np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]))
                    ax.set_xticklabels(np.array(["0", r"$\pi/2$", r"$\pi$", r"$3\pi/2$", r"$2\pi$"]))
    
                    ax.set_yticks(np.array([-1, 0, 1]))
                    ax.set_yticklabels(np.array([r"$y_\mathrm{min}$", "0", r"$y_\mathrm{max}$"]))
    
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • グラフのサイズ

                    # figsizeオプションで描画領域のサイズを変えることができる
                    # デフォルトは[6.4; 4.8]
                    fig = plt.figure(figsize = np.array([6.4, 4.8]) * 0.75) 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
                    ax.plot(x, np.sin(x))
    
                    plt.show()
                  
  • グラフの保存

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
                    ax.plot(x, np.sin(x))
    
                    # show()の代わりにsavefig("ファイル名")とすればグラフの保存ができる
                    # オプションでbbox_inches = "tight", pad_inches = 0.1とすれば周囲の余計な余白を極力小さくできる
                    # よく使う拡張子としてpngとpdfがある (拡張子で保存するファイルタイプを自動的に判断してくれる) 
                    plt.savefig("graph.png", bbox_inches = "tight", pad_inches = 0.1)
                  

複数のグラフ

  • 1つの軸に複数のグラフを描画する

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # ax.plotやax.scatterを繰り返し使うことで1つの軸に複数のグラフを描画できる
                    # 色は自動で変わる (勿論colorオプションで1つずつ指定できる) 
                    ax.plot(x, np.sin(x))
                    ax.plot(x, np.cos(x))
    
                    plt.show()
                  
  • plotとscatterの混在

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x1 = np.linspace(0, 2*np.pi, 100)
                    x2 = np.linspace(0, 2*np.pi, 10)
    
                    # ax.plotをax.scatterを混在させることもできる
                    # 色の管理はplotとscatterで別なので注意
                    ax.plot(x1, np.sin(x1))
                    ax.scatter(x2, np.cos(x2))
    
                    plt.show()
                  
  • 凡例の表示

                    fig = plt.figure() 
                    ax = fig.add_subplot(1, 1, 1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    # labelオプションで名前を付ける
                    ax.plot(x, np.sin(x), label = r"$\sin(x)$")
                    ax.plot(x, np.cos(x), label = r"$\cos(x)$")
    
                    # ax.legend()で、labelオプションで付けた名前を凡例として表示できる
                    ax.legend()
    
                    plt.show()
                  
  • 凡例の位置

                    fig = plt.figure() 
                    ax = fig.add_subplot(1,1,1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    ax.plot(x, np.sin(x), label = r"$\sin(x)$")
                    ax.plot(x, np.sin(x - 2*np.pi/5), label = r"$\sin(x-2\pi/5)$")
                    ax.plot(x, np.sin(x - 4*np.pi/5), label = r"$\sin(x-4\pi/5)$")
                    ax.plot(x, np.sin(x - 6*np.pi/5), label = r"$\sin(x-6\pi/5)$")
                    ax.plot(x, np.sin(x - 8*np.pi/5), label = r"$\sin(x-8\pi/5)$")
    
                    # 凡例の位置は自動で調節してくれるが、locで大まかな位置を指定できる
                    #  左上 "upper left"
                    # 中央上 "upper center"
                    #  右上 "upper right"
                    # 左中央 "center left"
                    #  中央 "center"
                    # 右中央 "center right"
                    #  左下 "lower left"
                    # 中央下 "lower center"
                    #  右下 "lower right"
                    ax.legend(loc = "center")
    
                    plt.show()
                  
  • 凡例の詳細位置

                    fig = plt.figure() 
                    ax = fig.add_subplot(1,1,1)
                    x = np.linspace(0, 2*np.pi, 100)
    
                    ax.plot(x, np.sin(x), label = r"$\sin(x)$")
                    ax.plot(x, np.sin(x - 2*np.pi/5), label = r"$\sin(x-2\pi/5)$")
                    ax.plot(x, np.sin(x - 4*np.pi/5), label = r"$\sin(x-4\pi/5)$")
                    ax.plot(x, np.sin(x - 6*np.pi/5), label = r"$\sin(x-6\pi/5)$")
                    ax.plot(x, np.sin(x - 8*np.pi/5), label = r"$\sin(x-8\pi/5)$")
    
                    # bbox_to_anchorで位置を指定できる。(0,0)が左下、(1,1)が右上
                    # さらにlocを指定すると凡例の位置をbbox_to_anchorに設定できる
                    # ncolsで列数を指定できる
    
                    ax.legend(bbox_to_anchor = (0.5, 1), loc = "lower center", ncols = 5)
    
                    plt.show()
                  
  • 左右に異なるy軸

                    fig = plt.figure() 
                    t = np.linspace(0, 0.9, 100)
    
                    # まずは左側 (通常) のy軸に対するグラフを作成する
                    ax1 = fig.add_subplot(1, 1, 1)
    
                    ax1.plot(t, 5 - 9.8 * t)
                    ax1.set_xlabel("時刻 [s]")
                    ax1.set_ylabel("速度 [m/s]")
    
                    # 右側のy軸に対するグラフを作成する
                    # twinxを用いて右側にy軸が来る軸の作成
                    ax2 = ax1.twinx()
    
                    # ax1とax2で色の管理が別なので注意
                    ax2.plot(t, - 4.9 * t ** 2 + 5 * t)
                    ax2.set_ylabel("高さ [m]")
    
                    plt.show()
                  
  • 左右に異なるy軸 (色、凡例の調整)

                    fig = plt.figure() 
                    t = np.linspace(0, 0.9, 100)
    
                    ax1 = fig.add_subplot(1, 1, 1)
    
                    ax1.plot(t, 5 - 9.8 * t, label = "速度 (摩擦なし) ")
                    ax1.plot(t, 24.6 * np.exp(- t / 2) - 19.6, label = "速度 (摩擦あり) ")
                    ax1.set_xlabel("時刻 [s]")
                    ax1.set_ylabel("速度 [m/s]")
                    ax1.legend()
    
                    ax2 = ax1.twinx()
    
                    ax2.plot(t, - 4.9 * t ** 2 + 5 * t, label = "高さ (摩擦なし) ", color = "tab:green")
                    ax2.plot(t, 49.2 * (1 - np.exp(- t / 2)) - 19.6 * t, label = "高さ (摩擦あり) ", color = "tab:red")
                    ax2.set_ylabel("高さ [m]")
                    ax2.legend()
    
                    plt.show()
                  
  • 複数の軸

                    # 複数の軸を描画するので描画領域の大きさを必ず設定しておく
                    fig = plt.figure(figsize = np.array([6.4 * 2, 4.8 * 3]) * 0.8) 
                    x1 = np.linspace(- np.pi, np.pi, 100)
                    x2 = np.linspace(-1, 1, 100)
                    x3 = np.linspace(-2, 2, 100)
                    x4 = np.linspace(1, 2, 100)
    
                    # 縦3行横2列に軸を並べたときの1つめ、という意味
                    ax = fig.add_subplot(3, 2, 1)
                    ax.plot(x1, np.sin(x1), label = r"$\sin(x)$")
                    ax.plot(x1, np.cos(x1), label = r"$\cos(x)$")
                    ax.plot(x1, np.tan(x1), label = r"$\tan(x)$")
                    ax.set_ylim(-1.5, 1.5)
                    ax.set_xlabel(r"$x$")
                    ax.set_title("三角関数のグラフ")
                    ax.legend()
    
                    # 縦3行横2列に軸を並べたときの2つめ、という意味
                    ax = fig.add_subplot(3, 2, 2)
                    ax.plot(x3, np.sinh(x3), label = r"$\sinh(x)$")
                    ax.plot(x3, np.cosh(x3), label = r"$\cosh(x)$")
                    ax.plot(x3, np.tanh(x3), label = r"$\tanh(x)$")
                    ax.set_xlabel(r"$x$")
                    ax.set_title("双曲線関数のグラフ")
                    ax.legend()
    
                    # 縦3行横2列に軸を並べたときの3つめ、という意味
                    ax = fig.add_subplot(3, 2, 3)
                    ax.plot(x1, 1 / np.sin(x1), label = r"$\csc(x)$")
                    ax.plot(x1, 1 / np.cos(x1), label = r"$\sec(x)$")
                    ax.plot(x1, 1 / np.tan(x1), label = r"$\cot(x)$")
                    ax.set_ylim(-10, 10)
                    ax.set_xlabel(r"$x$")
                    ax.set_title("三角関数の逆数のグラフ")
                    ax.legend()
    
                    # 縦3行横2列に軸を並べたときの4つめ、という意味
                    ax = fig.add_subplot(3, 2, 4)
                    ax.plot(x3, 1 / np.sinh(x3), label = r"$\mathrm{csch}(x)$")
                    ax.plot(x3, 1 / np.cosh(x3), label = r"$\mathrm{sech}(x)$")
                    ax.plot(x3, 1 / np.tanh(x3), label = r"$\coth(x)$")
                    ax.set_ylim(-4, 4)
                    ax.set_xlabel(r"$x$")
                    ax.set_title("双曲線関数の逆数のグラフ")
                    ax.legend()
    
                    # 縦3行横2列に軸を並べたときの5つめ、という意味
                    ax = fig.add_subplot(3, 2, 5)
                    ax.plot(x2, np.arcsin(x2), label = r"$\sin^{-1}(x)$")
                    ax.plot(x2, np.arccos(x2), label = r"$\cos^{-1}(x)$")
                    ax.plot(x3, np.arctan(x3), label = r"$\tan^{-1}(x)$")
                    ax.set_xlabel(r"$x$")
                    ax.set_title("逆三角関数のグラフ")
                    ax.legend()
    
                    # 縦3行横2列に軸を並べたときの6つめ、という意味
                    ax = fig.add_subplot(3, 2, 6)
                    ax.plot(x3, np.arcsinh(x3), label = r"$\sinh^{-1}(x)$")
                    ax.plot(x4, np.arccosh(x4), label = r"$\cosh^{-1}(x)$")
                    ax.plot(x2, np.arctanh(x2), label = r"$\tanh^{-1}(x)$")
                    ax.set_xlabel(r"$x$")
                    ax.set_title("逆双曲線関数のグラフ")
                    ax.legend()
    
                    # subplots_adjustで軸の間隔を調整
                    # wspaceが横方向、hspaceが縦方向
                    plt.subplots_adjust(wspace=0.2, hspace=0.3)
    
                    plt.show()
                  

対数スケールのグラフ

  • 片対数グラフ

                    fig = plt.figure() 
                    x = np.linspace(0, 5, 5)
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # ax.set_yscale("log")で片対数グラフ (y軸が対数スケール) となる
                    ax.set_yscale("log")
    
                    ax.plot(x, 5 * np.exp(- 2 * x), marker = "o")
                    ax.set_title("片対数グラフでは指数関数が直線となる")
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$5e^{-2x}$")
    
                    plt.show()
                  
  • 両対数グラフ

                    fig = plt.figure() 
                    x = np.linspace(1, 100, 10)
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # ax.set_xscale("log")を追加して両対数グラフ (x軸、y軸が対数スケール) となる
                    ax.set_xscale("log")
                    ax.set_yscale("log")
    
                    ax.plot(x, 10 * x ** (- 5 / 3), marker = "o")
                    ax.set_title("両対数グラフではべき関数が直線となる")
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$10x^{-5/3}$")
    
                    plt.show()
                  
  • 対数グラフでticks (軸の数値の設定) を使うときはticklabelsと併用すると良い (というか併用しないと上手く表示されないことがある)

                    # 対数スケールのグラフでは基本的に小目盛りが表示されたままとなる
                    # 無理やり消したい場合は次の記述を加えると良い
                    plt.rcParams["ytick.minor.size"] = 0 # x軸が対数スケールの場合にはxtick.minorとする
    
                    fig = plt.figure() 
                    x = np.linspace(0, 5, 5)
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    ax.set_yscale("log")
    
                    # y軸に設定したい数値のベクトルを設定しておく
                    vector_y = np.array([0.02, 0.7, 1.4, 5])
                    ax.set_yticks(vector_y)
                    ax.set_yticklabels(vector_y)
    
                    ax.plot(x, 5 * np.exp(- 2 * x), marker = "o")
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$5e^{-2x}$")
    
                    plt.show()
                  

ヒストグラム

  • 基本的なヒストグラム

                    fig = plt.figure() 
                    x = np.hstack([np.random.normal(0, 1, 1000), np.random.normal(5, 2, 1000)])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # ax.hist(ベクトル)でヒストグラムとなる
                    ax.hist(x)
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel("頻度")
    
                    plt.show()
                  
  • 階級数を変える

                    fig = plt.figure() 
                    x = np.hstack([np.random.normal(0, 1, 1000), np.random.normal(5, 2, 1000)])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # binsオプションで階級数を指定できる
                    ax.hist(x, bins = 20)
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel("頻度")
    
                    plt.show()
                  
  • 頻度ではなく確率分布にする

                    fig = plt.figure() 
                    x = np.hstack([np.random.normal(0, 1, 1000), np.random.normal(5, 2, 1000)])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # density = Trueで頻度ではなく確率分布となる
                    ax.hist(x, bins = 20, density = True)
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$p(x)$")
    
                    plt.show()
                  
  • 棒を外枠のみにする (複数のヒストグラムを表示するのに便利)

                    fig = plt.figure() 
                    x1 = np.random.normal(0, 1, 1000)
                    x2 = np.random.normal(5, 2, 1000)
                    x3 = np.hstack([x1, x2])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # histtype = "step"で外枠のみとなる
                    ax.hist(x1, bins = 20, density = True, histtype = "step", label = r"$p_1(x)$")
                    ax.hist(x2, bins = 20, density = True, histtype = "step", label = r"$p_2(x)$")
                    ax.hist(x3, bins = 20, density = True, histtype = "step", label = r"$p_{1 + 2}(x)$")
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$p(x)$")
                    ax.legend()
    
                    plt.show()
                  
  • ヒストグラムに関する注意点

    折れ線グラフのヒストグラムなど、より高度なものをプロットしたい場合はヒストグラムのベクトルを得なければならない。StatsBaseのfit関数によって得ることができるが、結構面倒くさい (このあたりはPython (numpy) の圧倒的勝ち)。

scatterによる散布図における点の色と点のサイズ

  • scatterによる散布図で点の色に対して、別のベクトルを指定する

                    fig = plt.figure() 
                    height = np.array([172.3, 165, 179.6, 174.5, 173.8, 165.4, 164.5, 174.9, 166.8, 185])
                    mass = np.array([75.24, 55.8, 78, 71.1, 67.7, 55.4, 63.7, 77.2, 67.5, 84.6])
                    fat = np.array([21.3, 15.7, 20.1, 18.4, 17.1, 22, 32.2, 36.9, 27.6, 14.4])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # cオプションでベクトルを指定することにより、そのベクトルの値に対応した点の色になる
                    ax.scatter(height, mass, c = fat)
    
                    ax.set_xlabel("身長 [cm]")
                    ax.set_ylabel("体重 [kg]")
    
                    plt.show()
                  
  • 色と数値を対応させるカラーバーを表示

                    fig = plt.figure() 
                    height = np.array([172.3, 165, 179.6, 174.5, 173.8, 165.4, 164.5, 174.9, 166.8, 185])
                    mass = np.array([75.24, 55.8, 78, 71.1, 67.7, 55.4, 63.7, 77.2, 67.5, 84.6])
                    fat = np.array([21.3, 15.7, 20.1, 18.4, 17.1, 22, 32.2, 36.9, 27.6, 14.4])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # 散布図scatter自体を変数として代入 (今の場合はc_pointsという変数)
                    c_points = ax.scatter(height, mass, c = fat)
    
                    # fig.colorbar(c_points)でカラーバーが追加される
                    fig.colorbar(c_points)
    
                    ax.set_xlabel("身長 [cm]")
                    ax.set_ylabel("体重 [kg]")
    
                    plt.show()
                  
  • 色、カラーバーに関するオプション1

                    fig = plt.figure() 
                    height = np.array([172.3, 165, 179.6, 174.5, 173.8, 165.4, 164.5, 174.9, 166.8, 185])
                    mass = np.array([75.24, 55.8, 78, 71.1, 67.7, 55.4, 63.7, 77.2, 67.5, 84.6])
                    fat = np.array([21.3, 15.7, 20.1, 18.4, 17.1, 22, 32.2, 36.9, 27.6, 14.4])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # vmaxオプションとvminオプションで色に対する最大値と最小値を設定できる
                    c_points = ax.scatter(height, mass, c = fat, vmin = 10, vmax = 40)
    
                    # labelオプションでカラーバーに名前が付く
                    fig.colorbar(c_points, label = "体脂肪率 [%]")
    
                    ax.set_xlabel("身長 [cm]")
                    ax.set_ylabel("体重 [kg]")
    
                    plt.show()
                  
  • 色、カラーバーに関するオプション2

                    fig = plt.figure() 
                    height = np.array([172.3, 165, 179.6, 174.5, 173.8, 165.4, 164.5, 174.9, 166.8, 185])
                    mass = np.array([75.24, 55.8, 78, 71.1, 67.7, 55.4, 63.7, 77.2, 67.5, 84.6])
                    fat = np.array([21.3, 15.7, 20.1, 18.4, 17.1, 22, 32.2, 36.9, 27.6, 14.4])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # cmapオプションで色使いが変えられる
                    # viridis : デフォルトの青→黄色
                    # jet : 虹色
                    # hsv : 周期的な虹色
                    c_points = ax.scatter(height, mass, c = fat, cmap = "hsv")
    
                    # ticksオプションで設定した値が表示される
                    # さらにカラーバー自体を別の変数に代入し (今の場合はcbar) 、cbar.ax.set_yticklabelsで、表示を変えられる
                    cbar = fig.colorbar(c_points, label = "体脂肪率 [%]", ticks = np.array([15, 25, 35]))
                    cbar.ax.set_yticklabels(np.array(["低", "中", "高"]))
    
                    ax.set_xlabel("身長 [cm]")
                    ax.set_ylabel("体重 [kg]")
    
                    plt.show()
                  
  • 点のサイズ

                    fig = plt.figure() 
                    height = np.array([172.3, 165, 179.6, 174.5, 173.8, 165.4, 164.5, 174.9, 166.8, 185])
                    mass = np.array([75.24, 55.8, 78, 71.1, 67.7, 55.4, 63.7, 77.2, 67.5, 84.6])
                    fat = np.array([21.3, 15.7, 20.1, 18.4, 17.1, 22, 32.2, 36.9, 27.6, 14.4])
                    age = np.array([27, 25, 31, 32, 28, 36, 42, 33, 54, 28])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # sオプションで点のサイズを決められる
                    # (plotの場合はmarkersize)
                    # ただしscatterの場合はcにベクトルを指定することによって点ごとのサイズを変えられる
                    c_points = ax.scatter(height, mass, c = fat, s = age * 4)
    
                    cbar = fig.colorbar(c_points, label = "体脂肪率 [%]", ticks = np.array([15, 25, 35]))
                    cbar.ax.set_yticklabels(np.array(["低", "中", "高"]))
    
                    ax.set_xlabel("身長 [cm]")
                    ax.set_ylabel("体重 [kg]")
                    ax.set_title("マーカーサイズは年齢に対応")
    
                    plt.show()
                  

imshow, pcolorを使ったヒートマップ

  • imshowは行列を見たまま表示するようなイメージ

                    fig = plt.figure() 
    
                    matrix = np.array([[2, 3, 0, 0],
                                       [1, 2, 3, 0],
                                       [0, 1, 2, 3]])
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # vmin, vmax, cmapオプションも使える (scatterのところを参照) 
                    c_matrix = ax.imshow(matrix)
    
                    # カラーバーも使える
                    # label, ticksオプションも使える
                    fig.colorbar(c_matrix, label = "行列の値")
    
                    ax.set_xlabel("列")
                    ax.set_ylabel("行")
    
                    plt.show()
                  
  • カラーバーの高さが気持ち悪い場合

                    fig = plt.figure() 
    
                    matrix = np.array([[2, 3, 0, 0],
                                       [1, 2, 3, 0],
                                       [0, 1, 2, 3]])
    
                    ax = fig.add_subplot(1,1,1)
    
                    c_matrix = ax.imshow(matrix)
    
                    # 手っ取り早くはfraction = (行の大きさ) / (列の大きさ) * 0.046, pad = 0.04で揃えられる
                    fig.colorbar(c_matrix, label = "行列の値", fraction = 3 / 4 * 0.046, pad = 0.04)
    
                    ax.set_xlabel("列")
                    ax.set_ylabel("行")
    
                    plt.show()
                  
  • pcolorは等高線のようなイメージで、x座標とy座標を指定できる
    ただし何も指定しないと、行列の行方向がxに、列がy方向になる (imshowと逆)

                    fig = plt.figure() 
    
                    # xとyの値に対するベクトルを作成する
                    x = np.linspace(-2*np.pi, 2*np.pi, 100)
                    y = np.linspace(-np.pi, np.pi, 100)
    
                    # xとyを行列にする
                    x, y = np.meshgrid(x, y)
    
                    ax = fig.add_subplot(1, 1, 1)
    
                    # 基本はax.pcolor(x座標を指定する行列, y座標を指定する行列, ヒートマップに対する行列, shading = "auto") 
                    # vmin, vmax, cmapオプションも使える (scatterのところを参照) 
                    c_pcolor = ax.pcolor(x, y, np.sin(x + y), shading = "auto")
    
                    # カラーバーも使える
                    # label, ticksオプションも使える
                    fig.colorbar(c_pcolor, label = r"$\sin(x+y)$")
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$y$")
                    ax.set_xticks(np.array([-2*np.pi, -np.pi, 0, np.pi, 2*np.pi]))
                    ax.set_xticklabels(np.array([r"$-2\pi$", r"$-\pi$", r"$0$", r"$\pi$", r"$2\pi$"]))
                    ax.set_yticks(np.array([-np.pi, 0, np.pi]))
                    ax.set_yticklabels(np.array([r"$-\pi$", r"$0$", r"$\pi$"]))
    
                    plt.show()
                  

3次元グラフ

  • 3次元グラフの基本

                    # 3次元グラフは基本的にマウスを使って視点を自由に変えられると便利である
                    # それを可能にするために別ウインドウでグラフを描画する必要がある
                    # %matplotlib tk (あるいはqt) とすれば別ウインドウでグラフが開く
                    # 逆に%matplotlib inlineとすればJupyter notebook上にグラフが表示される
                    %matplotlib tk
    
                    fig = plt.figure() 
                    t = np.linspace(0, 2*np.pi, 100)
                    x = np.sin(t)
                    y = np.cos(t)
                    z = t + np.sin(2 * t)
    
                    # projection = "3d"を追加することで3次元グラフとなる
                    ax = fig.add_subplot(1, 1, 1, projection = "3d")
    
                    # plotは3次元における折れ線グラフで、z座標のベクトルも必要になる
                    ax.plot(x, y, z)
    
                    # ax.set_zlabel, ax.set_zticks, ax.set_zticklabels, ax.set_zlimも使える
                    ax.set_xlabel(r"$x = \sin(t)$")
                    ax.set_ylabel(r"$y = \cos(t)$")
                    ax.set_zlabel(r"$z = t + \sin(2t)$")
    
                    plt.show()
                  
  • 散布図

                    %matplotlib tk
    
                    fig = plt.figure() 
                    age = np.array([27, 25, 31, 32, 28, 36, 42, 33, 54, 28])
                    height = np.array([172.3, 165, 179.6, 174.5, 173.8, 165.4, 164.5, 174.9, 166.8, 185])
                    mass = np.array([75.24, 55.8, 78, 71.1, 67.7, 55.4, 63.7, 77.2, 67.5, 84.6])
                    fat = np.array([21.3, 15.7, 20.1, 18.4, 17.1, 22, 32.2, 36.9, 27.6, 14.4])
    
                    ax = fig.add_subplot(1, 1, 1, projection = "3d")
    
                    # 3次元scatterは2次元と同様に色に対応するベクトルを指定できる
                    c_points = ax.scatter(height, mass, fat, c = age)
    
                    # カラーバーがデフォルトだとグラフに近いため、padオプションで少し離しておくと良い
                    plt.colorbar(c_points, label = "年齢 [歳]", pad = 0.15)
    
                    ax.set_xlabel("身長 [cm]")
                    ax.set_ylabel("体重 [kg]")
                    ax.set_zlabel("体脂肪率 [%]")
    
                    plt.show()
                  
  • 曲面 (ワイヤーフレーム) : pcolorに代わる表示方法

                    %matplotlib tk
    
                    fig = plt.figure() 
    
                    x = np.linspace(- 2*np.pi, 2*np.pi,100)
                    y = np.linspace(- np.pi, np.pi, 100)
    
                    x, y = np.meshgrid(x, y)
    
                    ax = fig.add_subplot(1, 1, 1, projection = "3d")
    
                    # ax.plot_wireframeで曲面表示
                    ax.plot_wireframe(x, y, np.sin(x) + np.cos(y))
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$y$")
                    ax.set_zlabel(r"$\sin(x)+\cos(y)$")
    
                    ax.set_xticks(np.array([-2*np.pi, -np.pi, 0, np.pi, 2*np.pi]))
                    ax.set_xticklabels(np.array([r"$-2\pi$", r"$-\pi$", r"$0$", r"$\pi$", r"$2\pi$"]))
                    ax.set_yticks(np.array([-np.pi, 0, np.pi]))
                    ax.set_yticklabels(np.array([r"$-\pi$", r"$0$", r"$\pi$"]))
    
                    plt.show()
                  
  • 色付き曲面

                    %matplotlib tk
    
                    fig = plt.figure() 
    
                    x = np.linspace(- 2*np.pi, 2*np.pi,100)
                    y = np.linspace(- np.pi, np.pi, 100)
    
                    x, y = np.meshgrid(x, y)
    
                    ax = fig.add_subplot(1, 1, 1, projection = "3d")
    
                    # cmapオプション付きのax.plot_surfaceで色付き曲面表示
                    c_surface = ax.plot_surface(x, y, np.sin(x) + np.cos(y), cmap = "viridis")
    
                    plt.colorbar(c_surface, pad = 0.15)
    
                    ax.set_xlabel(r"$x$")
                    ax.set_ylabel(r"$y$")
                    ax.set_zlabel(r"$\sin(x)+\cos(y)$")
    
                    ax.set_xticks(np.array([-2*np.pi, -np.pi, 0, np.pi, 2*np.pi]))
                    ax.set_xticklabels(np.array([r"$-2\pi$", r"$-\pi$", r"$0$", r"$\pi$", r"$2\pi$"]))
                    ax.set_yticks(np.array([-np.pi, 0, np.pi]))
                    ax.set_yticklabels(np.array([r"$-\pi$", r"$0$", r"$\pi$"]))
    
                    plt.show()
                  

アニメーション

  • アニメーションはいわゆるパラパラマンガの要領で作成する
    つまり、ある (短い) 時間だけグラフを表示する、という動作を繰り返す
    PyPlotの場合グラフ消去→グラフ表示を繰り返すことになる

                    # アニメーションも3次元グラフと同様に別ウインドウで表示する
                    # ちなみにmatplotlib.pyplot単体でアニメーションの保存は面倒なので諦めたほうが良い
                    %matplotlib tk
    
                    fig = plt.figure()
                    ax = fig.add_subplot(1, 1, 1)
    
                    q = np.pi / 4
                    v0 = 5.0
                    v0x = v0 * np.cos(q)
                    v0y = v0 * np.sin(q)
                    g = 9.8
    
                    t = np.array([0.0])
                    x = np.array([0.0])
                    y = np.array([0.0])
    
                    # アニメーションを表示するためのfor文
                    for it in range(200):
    
                        t_now = it * 0.0035
                        x_now = v0x * t_now
                        y_now = v0y * t_now - 0.5 * g * t_now ** 2
                                
                        t = np.append(t, t_now)
                        x = np.append(x, x_now)
                        y = np.append(y, y_now)
                                
                        # グラフの描画
                                
                        # 前のグラフを一旦消去
                        ax.cla()
                                
                        # 新しいグラフのプロット
                        ax.scatter(x_now, y_now)
                        ax.plot(x, y)
                                
                        ax.set_xlabel("水平距離 [m]")
                        ax.set_ylabel("垂直距離 [m]")
                                
                        # 軸の最大、最小は決めておいたほうが良い
                        ax.set_xlim(0, 3)
                        ax.set_ylim(0, 0.8)
                                
                        ax.set_title("t = " + "{:5.3f}".format(t_now) + " [秒]")
    
                        # グラフを描画し、() の中の時間 (秒) だけ待つ
                        plt.pause(0.05)