LoginSignup
1
2

More than 1 year has passed since last update.

例題演習matplotlib(4):Legend(凡例)の設定

Last updated at Posted at 2021-05-15

例題(4):凡例の設定

凡例(Legend)関連の設定について学ぶ.

例(1):サンプルコード

基準となるサンプルコードを以下に示す.

plot04_example1.py
import numpy as np                  # numpy
import matplotlib.pyplot as plt     # matplotlib plt
import matplotlib.ticker as ticker  # matplotlib ticker


def main():
    '''main program'''

    # setting
    f_out = 'graph04_example1.png'   # output file (figure)

    # data
    x = np.arange(0, 10.1, 0.1)
    y1 = -np.sin(x)
    y2 = np.sin(x)
    y3 = np.cos(x)
    data = {'p1': [x, y1, r'$y=-\sin(x)$'],  # packing
            'p2': [x, y2, r'$y=\sin(x)$'],
            'p3': [x, y3, r'$y=\cos(x)$']}

    # plot graph
    run_plot(f_out, data)


def run_plot(f_out, data):
    '''plot graph
    [input]
    f_out: output file name
    data: data for plotting (x, y, label)
    '''

    # (0) setting of matplotlib
    # graph
    gx = 14                     # graph size of x [cm]
    gy = 6                      # graph size of y [cm]
    dpi = 200                   # graph DPI (100~600程度)

    # font
    f_family = 'IPApGothic'     # font (sans-serif, serif, IPApGothic)
    font_ax = {'size': 10, 'color': 'k'}  # 軸ラベルのフォント
    fs_le = 9                             # 凡例のフォントサイズ
    fs_ma = 9                             # 主目盛りのフォントサイズ

    # 軸ラベル
    x_label = 'X'               # x軸ラベル
    y_label = 'Y'               # y軸ラベル

    # 軸範囲
    x_s = 0                     # x軸の最小値
    x_e = 10                    # x軸の最大値
    y_s = -1.1                  # y軸の最小値
    y_e = 1.1                   # y軸の最大値

    # 目盛り
    x_ma = 1                    # x軸の主目盛り間隔
    x_mi = 0.2                  # x軸の副目盛り間隔
    y_ma = 0.5                  # y軸の主目盛り間隔
    y_mi = 0.1                  # y軸の副目盛り間隔

    # (A) Figure
    # (A.1) Font or default parameter
    # https://matplotlib.org/stable/api/matplotlib_configuration_api.html
    plt.rcParams['font.family'] = f_family

    # (A.2) Figureの作成
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.figure.html
    # [Returns]
    #   Figureオブジェクトが返される。
    # [Parameter]
    # figsize=(6.4,4.8): グラフサイズ(x,y), 1[cm]=1/2.54[in]
    # dpi=100: 出力DPI
    tl = False                  # Figureのスペース自動調整
    fc = 'w'                    # Figureの背景色
    ec = None                   # 枠線の色
    lw = None                   # 枠線の幅
    fig = plt.figure(figsize=(gx/2.54, gy/2.54), dpi=dpi,
                     tight_layout=tl, facecolor=fc, edgecolor=ec,
                     linewidth=lw)

    # (A.3) グラフ間隔の調整(pltまたはfig)
    # bottom等はfigure()でtigit_layout=Trueにすれば不要
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
    bottom = 0.18                # グラフ下側の位置(0~1)
    top = 0.95                  # グラフ上側の位置(0~1)
    left = 0.12                 # グラフ左側の位置(0~1)
    right = 0.97                # グラフ右側の位置(0~1)
    hspace = 0.2                # グラフ(Axes)間の上下余白
    wspace = 0.2                # グラフ(Axes)間の左右余白
    fig.subplots_adjust(bottom=bottom, top=top, left=left, right=right,
                        hspace=hspace, wspace=wspace)

    # (B) Axes
    # (B.1) Axesの追加
    # 複数のグラフをタイル状に作成することができる。
    # 複数グラフの配置を細かく設定する場合はadd_axes()やadd_gridspec()。
    # https://matplotlib.org/stable/api/figure_api.html
    # [Returns]
    #   Axesオブジェクトが返される。
    # [Parameter]
    # *args=(1,1,1): 行番号,列番号,インデックス
    #   1つのFigureに複数のAxesを作る場合に指定する。
    #   add_subplot(2,1,1): 2行のAxesを作り、その1番目(上側)
    #   add_subplot(211): 2,1,1と同じだが、簡略記法
    # projection='rectilinear': グラフの投影法(polarなど)
    # sharex: x軸を共有する際に、共有元のAxisを指定する。
    # sharey: sharexのy軸版
    # label: Axesに対する凡例名(通常は使わない)
    n_row = 1                   # 全グラフの行数
    n_col = 1                   # 全グラフの列数
    n_ind = 1                   # グラフ番号
    fc = 'w'                    # Axesの背景色(通常は白)
    ax = fig.add_subplot(n_row, n_col, n_ind, fc=fc)

    # (B.2) 軸ラベル(axis label)の設定
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html
    # [Parameter]
    # xlabel: 軸ラベル
    # loc='center': 軸ラベル位置(x: left,center,right; y:bottom,center,top)
    # labelpad: 軸ラベルと軸間の余白
    # fonddict: 軸ラベルのText設定
    ax.set_xlabel(x_label, fontdict=font_ax)  # x軸ラベルの設定
    ax.set_ylabel(y_label, fontdict=font_ax)  # y軸ラベルの設定

    # (B.3) 軸の種類の設定
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xscale.html
    xscale = 'linear'          # x軸の種類(linear, log, symlog, logit)
    yscale = 'linear'          # y軸の種類(linear, log, symlog, logit)
    ax.set_xscale(xscale)      # x軸の種類
    ax.set_yscale(yscale)      # y軸の種類

    # (B.4) 軸の範囲の設定
    # 自動で設定する場合は、auto=Trueのみにする
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html
    ax.set_xlim(x_s, x_e, auto=False)  # x軸の範囲
    ax.set_ylim(y_s, y_e, auto=False)  # y軸の範囲

    # (B.5) 軸のアスペクト比
    # x軸とy軸の比率を強制的に設定する場合に行う。
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_aspect.html
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_box_aspect.html
    asp_a = 'auto'          # auto:自動, [数値]:x,yの比率
    asp_b = None            # None:自動, [数値]:x,yのグラフ長さの比率
    ax.set_aspect(asp_a)    # X軸とY軸の比率を設定する
    ax.set_box_aspect(asp_b)   # X軸とY軸のグラフ長さの比率を設定する

    # (B.6) 目盛り関係の設定
    # (B.6.1)主目盛りの位置(Locator)
    # https://matplotlib.org/stable/api/ticker_api.html
    mal_x = ticker.MultipleLocator(x_ma)  # 等間隔目盛り
    # mal_x = ticker.IndexLocator(x_ma, x_off) # 等間隔目盛り(+offset)
    # mal_x = ticker.LogLocator(base=10) # 対数目盛り
    # mal_x = ticker.AutoLocator()         # 自動目盛り
    # mal_x = ticker.NullLocator()         # 目盛りなし
    # mal_x = ticker.LinearLocator(nx_ma)  # 個数指定目盛り
    # mal_x = ticker.FixedLocator([0, 1, 3]) # 位置指定目盛り
    mal_y = ticker.MultipleLocator(y_ma)  # 等間隔目盛り
    # mal_y = ticker.IndexLocator(y_ma, y_off)  # 等間隔目盛り(+offset)
    # mal_y = ticker.LogLocator(base=10) # 対数目盛り
    # mal_y = ticker.AutoLocator()         # 自動目盛り
    # mal_y = ticker.NullLocator()         # 目盛りなし
    # mal_y = ticker.LinearLocator(ny_ma)  # 個数指定目盛り
    # mal_y = ticker.FixedLocator([-1, 0, 1]) # 位置指定目盛り
    ax.xaxis.set_major_locator(mal_x)    # x軸の主目盛り間隔の設定
    ax.yaxis.set_major_locator(mal_y)    # y軸の主目盛り間隔の設定

    # (B.6.2)主目盛りの表記(Formatter)
    # https://matplotlib.org/stable/api/ticker_api.html
    maf_x = ticker.ScalarFormatter()  # 数値
    # maf_x = ticker.NullFormatter() # 目盛り表記なし
    # maf_x = ticker.FixedFormatter(['A','B','C','D','E','F']) # 指定表記
    # maf_x = ticker.StrMethodFormatter('{x:.1f}m') # format記法
    # maf_x = ticker.LogFormatterMathtext(base=10)  # log記法(10^x)
    maf_y = ticker.ScalarFormatter()  # 数値
    # maf_y = ticker.NullFormatter() # 目盛り表記なし
    # maf_y = ticker.FixedFormatter(['A','B','C','D','E','F']) # 指定表記
    # maf_y = ticker.StrMethodFormatter('{x:.1f}m') # format記法
    # maf_y = ticker.LogFormatterMathtext(base=10)  # log記法(10^x)
    ax.xaxis.set_major_formatter(maf_x)  # x軸の主目盛り表記の設定
    ax.yaxis.set_major_formatter(maf_y)  # y軸の主目盛り表記の設定

    # (B.6.3) 副目盛りの位置(Locator)
    # https://matplotlib.org/stable/api/ticker_api.html
    mil_x = ticker.MultipleLocator(x_mi)  # 等間隔目盛り
    # mil_x = ticker.IndexLocator(x_mi, x_off)  # 等間隔目盛り(+offset)
    # mil_x = ticker.LogLocator(base=10, subs=np.arange(2, 10)*0.1) # 対数目盛り
    # mil_x = ticker.AutoLocator()         # 自動目盛り
    # mil_x = ticker.NullLocator()         # 目盛りなし
    # mil_x = ticker.LinearLocator(nx_mi)  # 個数指定目盛り
    mil_y = ticker.MultipleLocator(y_mi)  # 等間隔目盛り
    # mil_y = ticker.IndexLocator(y_mi, y_off)  # 等間隔目盛り(+offset)
    # mil_y = ticker.LogLocator(base=10, subs=np.arange(2, 10)*0.1) # 対数目盛り
    # mil_y = ticker.AutoLocator()         # 自動目盛り
    # mil_y = ticker.NullLocator()         # 目盛りなし
    # mil_y = ticker.LinearLocator(ny_mi)  # 個数指定目盛り
    ax.xaxis.set_minor_locator(mil_x)  # x軸の副目盛り間隔の設定
    ax.yaxis.set_minor_locator(mil_y)  # y軸の副目盛り間隔の設定

    # (B.6.4) 副目盛りの表記(Formatter)
    # https://matplotlib.org/stable/api/ticker_api.html
    mif_x = ticker.NullFormatter()       # 目盛り表記なし
    mif_y = ticker.NullFormatter()       # 目盛り表記なし
    ax.xaxis.set_minor_formatter(mif_x)  # x軸の副目盛り表記の設定
    ax.yaxis.set_minor_formatter(mif_y)  # y軸の副目盛り表記の設定

    # (B.6.5) 目盛り関連の細部の設定
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.tick_params.html
    # [Parameter]
    # axis: 対象軸(x, y, both)
    # which: major, minor, both
    # labelsize: フォントサイズ
    # top, right, bottom, left: Tickを表記する場所(Trueで表記)
    # labeltop: Trueで上側にも目盛りを付ける(labelrightも同様)
    # labelrotation: 目盛りの表記角度
    # labelcolor: 目盛り表記の色
    # pad: 軸と目盛りの間隔
    # color: 目盛り線の色
    ax.tick_params(axis='both', which='major', labelsize=fs_ma,
                   top=True, right=True)
    ax.tick_params(axis='both', which='minor', top=True, right=True)

    # (B.7) グリッドの設定
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.grid.html
    gb = False   # 出力の有無(Falseかつ、lsなどの指定なしで、出力なし)
    which = 'major'  # 目盛りの指定(major, minor, both)
    axis = 'both'    # X,Y軸の指定(x, y, both)
    color = 'gray'   # 線色
    ls = '-'         # 線種('-', '--', '-.', ':')
    lw = 0.5         # 線幅
    ax.grid(b=gb, which=which, axis=axis)  # Falseの場合
    # ax.grid(b=gb, which=which, axis=axis, c=color, ls=ls, lw=lw)

    # (B.8) 直線
    # axhline(), axvline(): 横線, 縦線(端から端まで)
    # axhspan(), asvspan(): 横線, 縦線(始点と終点指定)
    # axline(): 直線
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.axhline.html
    # [Parameter]
    # py = 0                      # 横線の位置(y座標)
    # color = 'k'                 # 線色
    # ls = '-'                    # 線種('-', '--', '-.', ':')
    # lw = 0.5                    # 線幅
    # ax.axhline(y=py, c=color, ls=ls, lw=lw)

    # (C) Plot
    # (C.2) scatter(): 散布図
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html
    # [Returns]
    #   PathCollectionオブジェクトが返される
    # [Parameter]
    # x, y: x, yデータ(リストなど)
    # その他、scatterの設定値(plotと異なるので注意)
    d_x = data['p1'][0]        # x data(適宜変更)
    d_y = data['p1'][1]        # y data(適宜変更)
    label = data['p1'][2]      # 凡例(なしはNone)
    ms = 2                     # markerサイズ
    mfc = 'w'                  # markerの色(none, k, r, g, b, w, etc.)
    marker = 's'        # marker(o, s, v, ^, D, +, x, etc.; None=なし)
    mec = 'b'           # markerの線色(k, r, g, b, etc.)
    mew = 0.3           # markerの線幅
    p1 = ax.scatter(d_x, d_y, label=label, s=ms, c=mfc, marker=marker,
                    linewidths=mew, edgecolors=mec)    

    # (C.1) plot(): 折れ線グラフ
    # 散布図はscatter()
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html
    # [Returns]
    #   Line2Dオブジェクト(配列)が返される。
    # [Parameter]
    # *args: xデータ, yデータ, [fmt]
    #   x,yデータはx軸とy軸のデータ(リストなど)
    #   fmtは線や点の簡易的記法による指定
    # *kwargs: Line2Dの設定値(多数あり)
    d_x = data['p2'][0]         # x data(適宜変更)
    d_y = data['p2'][1]         # y data(適宜変更)
    label = data['p2'][2]       # 凡例(なしはNone)
    ls = '-'                       # 線種('-', '--', '-.', ':')
    lw = 0.5                       # 線幅
    color = 'k'                    # 線色(k, r, g, b, etc.)
    marker = 'None'     # marker(o, s, v, ^, D, +, x, etc.; None=なし)
    mec = 'k'           # markerの線色(k, r, g, b, etc.)
    mew = 0.5           # markerの線幅
    mfc = 'w'           # markerの色(none, k, r, g, b, w, etc.)
    ms = 2              # markerサイズ
    markevery = None    # markerの出力間隔(None=全部, 2は2個毎)
    p2 = ax.plot(d_x, d_y, label=label, ls=ls, lw=lw, c=color,
                 marker=marker, mec=mec, mew=mew, mfc=mfc, ms=ms,
                 markevery=markevery)

    # (C.1) plot(): 折れ線グラフ
    d_x = data['p3'][0]         # x data(適宜変更)
    d_y = data['p3'][1]         # y data(適宜変更)
    label = data['p3'][2]       # 凡例(なしはNone)
    ls = '--'                       # 線種('-', '--', '-.', ':')
    lw = 0.7                       # 線幅
    color = 'r'                    # 線色(k, r, g, b, etc.)
    marker = 'None'        # marker(o, s, v, ^, D, +, x, etc.; None=なし)
    mec = 'k'           # markerの線色(k, r, g, b, etc.)
    mew = 0.5           # markerの線幅
    mfc = 'w'           # markerの色(none, k, r, g, b, w, etc.)
    ms = 2              # markerサイズ
    markevery = None    # markerの出力間隔(None=全部, 2は2個毎)
    p3 = ax.plot(d_x, d_y, label=label, ls=ls, lw=lw, c=color,
                 marker=marker, mec=mec, mew=mew, mfc=mfc, ms=ms,
                 markevery=markevery)


    # (D) Others: 凡例、テキストなど
    # (D.1) 凡例
    # (D.1.1) 凡例データの一覧を作成
    handles, labels = ax.get_legend_handles_labels()

    # (D.1.2) 凡例の作成
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html
    anc = (1, 1)                # 凡例の配置場所(0~1の相対位置)
    loc = 'upper right'  # 配置箇所:upper,center,lower; left,center,right; best
    ti = '凡例'          # 凡例のタイトル(なし=None or '')
    ti_fs = 9            # 凡例のタイトルのフォントサイズ
    ncol = 1             # 凡例の列数
    fc = 'w'             # 凡例の背景色(なし=none)
    ec = 'k'             # 枠線の色(なし=none)
    fa = 1.0             # 透明度(0で透明, 1で透明なし)
    bp = 0.5             # 凡例の枠の余白(default=0.4)
    ms = 1.0             # マーカーの倍率(default=1.0)
    sha = True           # True:影付き、False:影なし
    fb = True            # 凡例の角:True:丸、False:四角
    bap = 0.8            # 凡例の外側の余白(default=0.5)
    ls = 0.5             # 凡例間の上下余白
    cs = 2.0             # 凡例間の左右余白
    legend = ax.legend(handles, labels, title=ti,
                       title_fontsize=ti_fs, loc=loc,
                       bbox_to_anchor=anc, ncol=ncol, facecolor=fc,
                       edgecolor=ec, framealpha=fa, fontsize=fs_le,
                       borderpad=bp, shadow=sha, markerscale=ms,
                       fancybox=fb, labelspacing=ls, columnspacing=cs,
                       borderaxespad=bap)

    # (D.1.3) 凡例の細かい設定
    legend.get_frame().set_linestyle('-')  # 枠線の種類
    legend.get_frame().set_linewidth(0.5)  # 枠線の太さ

    # (D.2) テキスト
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.text.html
    # txt = '(a) Test Plot'    # テキスト文字列
    # px = 0.97                # x位置(transformで基準座標の変更)
    # py = 0.05                # y位置(transformで基準座標の変更)
    # tf = ax.transAxes        # 基準座標(ax.transAxes, fig.transFigure)
    # ha = 'right'             # 左右位置(left, center, right)
    # va = 'bottom'            # 上下位置(bottom, center, top, baseline)
    # rot = 0                  # 回転角度(左回転)
    # color = 'k'              # テキストの色
    # font_tx = {'size': 10}   # テキストのフォント
    # ax.text(x=px, y=py, s=txt, font=font_tx, ha=ha, va=va, color=color,
    #         rotation=rot, transform=tf)

    # (E) save figure
    # https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html
    # [Parameters]
    # fname: 出力ファイル名
    # dpi: 出力DPI(Figure設定時のdpiが優先)
    print(f'write: {f_out}')
    plt.savefig(fname=f_out)    # save figure

    # (F) close
    plt.close()


if __name__ == '__main__':
    main()

グラフの出力結果は以下の通り.
graph04_example1.png

解説

サンプルコードを基に,凡例表示の変更例を示す.

例(2):凡例の配置(グラフ内)

凡例の配置は,Axes.legend()の作成時に設定し,bbox_to_anchorlocで指定する.
サンプルコードで,関連する箇所のみを抜き出すと,次のように設定されている.

    anc = (1, 1)                # 凡例の配置場所(0~1の相対位置)
    loc = 'upper right'  # 配置箇所:upper,center,lower; left,center,right; best
    legend = ax.legend(handles, labels, title=ti,
                       title_fontsize=ti_fs, loc=loc,
                       bbox_to_anchor=anc, ncol=ncol, facecolor=fc,
                       edgecolor=ec, framealpha=fa, fontsize=fs_le,
                       borderpad=bp, shadow=sha, markerscale=ms,
                       fancybox=fb, labelspacing=ls, columnspacing=cs,
                       borderaxespad=bap)

このうち,ancはbbox_to_anchorの設定値であるが,グラフ(Axes)のグラフの配置ポイントを指定する.0~1の相対位置であるから,サンプルコードの設定値(1, 1)は右上を意味する.
例えば,(0, 0)は左下,(1, 0)は右下,(0.5, 0.5)はAxesの中心となる.

locの設定値locは,bbox_to_anchorを,凡例のどの部分に一致させるか指定する.サンプルコードでは,upper lightとしているため,凡例の「右上」を一致させることを意味する.

例として,anc = (0, 1)と変更してみると,次のグラフになる(locはそのまま).
graph04_example2_1.png
凡例の配置場所をAxesの左上(anc = (0, 1))としたが,凡例の配置箇所を右上(loc = 'upper right')としたままであるため,凡例が図からはみ出てしまった.

次に,anc = (0, 1)の変更と,loc = 'upper left'を変更すると,次のグラフになる.
graph04_example2_2.png
凡例の配置箇所を左上(loc = 'upper left')としたので,凡例がグラフ内に収まった.

例(3):凡例のオフセット(外側の余白)

凡例の設置個所は,例(2)の通りlocで指定するが,凡例枠と指定位置はオフセットされている.オフセットの距離は,borderaxespadで指定する.
サンプルコードの該当箇所を抜き出すと,以下の通り.

    bap = 0.8            # 凡例の外側の余白(default=0.5)
    legend = ax.legend(handles, labels, title=ti,
                       title_fontsize=ti_fs, loc=loc,
                       bbox_to_anchor=anc, ncol=ncol, facecolor=fc,
                       edgecolor=ec, framealpha=fa, fontsize=fs_le,
                       borderpad=bp, shadow=sha, markerscale=ms,
                       fancybox=fb, labelspacing=ls, columnspacing=cs,
                       borderaxespad=bap)

例えば,bap = 0と変更すると,オフセットがゼロになるので,凡例はグラフの右上とピッタリ一致する.
graph04_example3_1.png
なお,枠線とのオフセットであるから,この場合,影がはみ出ることになる.

例(4):グラフ(Axes)外への配置

上記の例(2), 例(3)を参考にすれば,グラフ(Axes)外へ凡例を配置させることもできる.
例えば,凡例をグラフ右側に配置するには,サンプルコードの以下の箇所を変更する(変更箇所のみ記述).

    # (A.3) グラフ間隔の調整(pltまたはfig)
    right = 0.72                # グラフ右側の位置(0~1)

    # (D.1.2) 凡例の作成
    anc = (1.05, 1)                # 凡例の配置場所(0~1の相対位置)
    loc = 'upper left'  # 配置箇所:upper,center,lower; left,center,right; best
    bap = 0.0            # 凡例の外側の余白(default=0.5)

グラフは以下のようになる.
graph04_example4_1.png

例(5):凡例の順番の変更

凡例の順番は,基本的に,データをプロットした順番である.ただし,scatter()よりplot()の順番が先に来るという謎仕様になっている.実際,サンプルコードはscatter()の"y=-sin(x)"を先に実行しているが,凡例では最後になっている.

凡例の順番は,legend()作成時にhandlesとlabelsをこちらで設定すれば変えることができる.

まず,サンプルコードでは,Axes.get_lagend_handles_labels()を使って,凡例となるハンドル(プロットしたオブジェクト)とラベルの配列を得ている.順番の変更には,このhandlesとlabelsを自分で設定すれば良い.

    # (D.l.1) 凡例データの一覧を作成
    handles, labels = ax.get_legend_handles_labels()

handlesには,plot()やscatter()での返り値(Line2Dオブジェクトなど)を配列で与える.lablesも,同様に,それらのラベル名を配列で与えれば良い.

サンプルコードでは,scatter()とplot()の返り値を,下記のように変数p1などに格納していた.

    p1 = ax.scatter(d_x, d_y, label=label, s=ms, c=mfc, marker=marker,
                    linewidths=mew, edgecolors=mec)

    p2 = ax.plot(d_x, d_y, label=label, ls=ls, lw=lw, c=color,
                 marker=marker, mec=mec, mew=mew, mfc=mfc, ms=ms,
                 markevery=markevery)

    p3 = ax.plot(d_x, d_y, label=label, ls=ls, lw=lw, c=color,
                 marker=marker, mec=mec, mew=mew, mfc=mfc, ms=ms,
                 markevery=markevery)

これらの変数をもとに,(D.1.1)でhandlesとlabelsを以下のように,指定する.

    # (D.1.1) 凡例データの一覧を作成
    # handles, labels = ax.get_legend_handles_labels()
    handles = [p1, p2[0], p3[0]]
    labels = [p1.get_label(), p2[0].get_label(), p3[0].get_label()]

handlesに,p1~p3を配列で与えているが,要注意なことは,p2とp3(plot()の返り値)は配列,ということである.これは1回のplot()で複数のデータのプロットができるためである(煩雑になるので奨励しない).よって,今回のように,1回のplot()で1データしかプロットしない場合は,最初の配列値(p2[0], p3[0])を使う.

labelsも同様に,p1~p3のラベル名を配列で与える.Line2DオブジェクトやPathCollectionオブジェクトにget_label()というラベル名を返す関数があるので,それを使えば良い.もちろん,文字列を直接指定することもできる.

作成されたグラフは次の通り.'y=-sin(x)'が凡例の最初に来ていることがわかる.
graph04_example5_1.png

演習

サンプルコードを基に,下記の演習問題を解答せよ.
解答はコメント欄を参照.

演習(1):凡例の配置と装飾

次のグラフのように,凡例の設定を変更せよ.
※凡例のタイトルなし,右下配置,透明度0.8,凡例内のマーカーサイズ3倍,影なし,凡例の枠を角丸.
graph04_hw01.png

演習(2):凡例のグラフ外配置

次のグラフのように,凡例の設定を変更せよ.
※図の余白修正,凡例をグラフの上側に配置,凡例タイトルなし,凡例の列数変更,凡例の背景なし,枠線なし,影なし,外側余白なし.
graph04_hw02.png

演習(3):凡例を逆順で表示

次のグラフのように,凡例を(サンプルコードと比べて)逆順で表示せよ.
※handlesとlabelsを逆順にする.
graph04_hw03.png

1
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2