Python matplotlibで学ぶ…グラフ描画プログラム

提供:yonewiki
2022年9月26日 (月) 12:50時点におけるYo-net (トーク | 投稿記録)による版 (ページの作成:「== '''概要''' == Python matplotlibを使って学ぶ統計処理 正規分布へ戻る  pythonによるグラフ描画プログラムを以下に示します。 <Syntaxhighlight lang="python" enclose="div" line> from pylab import * from matplotlib import rcParams import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.ticker as tick import sys as system import math import matplotlib.font_manager as fm from matplotlib.font_manager impo…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

概要

Python matplotlibを使って学ぶ統計処理 正規分布へ戻る


 pythonによるグラフ描画プログラムを以下に示します。

from pylab import *
from matplotlib import rcParams
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.ticker as tick
import sys as system
import math 
import matplotlib.font_manager as fm

from matplotlib.font_manager import FontProperties

#iPad Font Example
#fp=FontProperties(fname=r'/private/var/mobile/Containers/Shared/AppGroup/133F326C-1CD8-49C6-9B85-7BBA53194CA4/Pythonista3/Documents/site-packages/ipaexg.ttf')

#Windows Font
fp=FontProperties(fname=r'MS Gothic')

#図にグラフ(111)を追加
ax = fig.add_subplot(1, 1, 1, zorder=0)

#軸目盛りを追加
ax.tick_params(which='major',direction='inout', bottom = True, left = True, top = False, right = False, labelsize=5, width = 0.8, length = 4, color='black', zorder=1)
ax.tick_params(which='minor',direction='inout', bottom = True, left = True, top = False, right = False, labelsize=5, width = 0.5, length = 2, color='black', zorder=1)

#軸の目盛り線設定
ax.xaxis.grid(linewidth=0.2, which='minor', ls=':', zorder=-4)
ax.xaxis.grid(linewidth=0.3, which='major', ls='-', zorder=-5)
ax.yaxis.grid(linewidth=0.2, which='minor', ls=':', zorder=-6)
ax.yaxis.grid(linewidth=0.3, which='major', ls='-', zorder=-7)

#目盛りの範囲設定と目盛りの挿入位置設定
ax.set_ylim(-3.01, 3.01)
ax.set_yticks(np.arange( -3.0,  3.1, step = 1))
ax.set_yticks(np.arange( -3.0,  3.0, step = 0.25), minor=True)
ax.set_xlim(-8.01, 8.05)
ax.set_xticks(np.arange(-8, 8.1, step = 2))
ax.set_xticks(np.arange(-8, 8, step = 0.5), minor=True)

#グラフの枠の設定
ax.spines['bottom'].set_position('zero')
ax.spines['bottom'].set_linewidth(0.8)
ax.spines['bottom'].set_color('black')
ax.spines['left'].set_position('zero')
ax.spines['left'].set_linewidth(0.8)
ax.spines['left'].set_color('black')
ax.spines['top'].set_linewidth(0)
ax.spines['right'].set_linewidth(0)

#軸ラベル位置
ax.yaxis.set_label_coords(-0.03,  0.50)
ax.xaxis.set_label_coords( 0.50, -0.03)

#軸の基準位置に矢印を追加
ax.annotate(s='',xy=(0, 3.01),xytext=(0, -3.01),xycoords='data',\
            arrowprops=dict(facecolor='black',arrowstyle='->, head_width=0.3',lw=0.5,shrinkA=0,shrinkB=0))
ax.annotate(s='',xy=(8.05,  0),xytext=(-8.01,  0),xycoords='data',\
            arrowprops=dict(facecolor='black',arrowstyle='->, head_width=0.3',lw=0.5,shrinkA=0,shrinkB=0))

#グリッドをグラフデータの後ろに隠す。
ax.set_axisbelow(True)

#グリッド有効化
ax.grid(True, zorder=-1)

#グラフの位置
ax.set_position([0.2, 0.2, 0.7, 0.6])

#ラベルの文字設定
ax.set_xlabel('x [-]', fontsize = 6, fontdict={'family': 'Meiryo'})
ax.set_ylabel('y = f(x)[-]', fontsize = 6, fontdict={'family': 'Meiryo'})
ax.set_title('散布図の連続描画による関数グラフ', fontsize = 8, fontdict={'family': 'Meiryo'})


u = 0
sigma = 1 #sigmaの初期値
while sigma < 2:#sigmaの値を変えて複数の線を描画したい場合はココを増加させたり、初期値を変えたりする。

  if sigma != 0: #sigmaが0のときは計算不能なので、処理しない。関数独自のエラー回避。
    
    #確率密度関数の計算結果をx配列値全てについて計算し、yに配列として格納
    y = 1 / (np.sqrt(2 * np.pi) * sigma) * np.power(math.e ,-1 / (2 * np.power(sigma, 2))  * np.power((x - u), 2))

    #グラフとy軸基準の内側を塗りつぶす設定。斜線パターン
    plt.fill_between(x, y, facecolor="none", alpha=0.8, edgecolor='#1f77b4', hatch="//////", zorder = 15) #hach Pattern = / \ | - + x o O . * #1f77b4
    
    #xとsの関係をグラフに連続値としてプロット
    ax.plot(x, y, linestyle='solid', linewidth = 0.8, zorder = 15 + sigma)
    
  #次のsigmaの値について描画?この例ではsigmaが1のときの1回だけプロットして終わる。
  sigma += 1

#プロット結果を標準出力で表示  
plt.show()

 

12行目/13行目

#iPad Font Example
#fp=FontProperties(fname=r'/private/var/mobile/Containers/Shared/AppGroup/133F326C-1CD8-49C6-9B85-7BBA53194CA4/Pythonista3/Documents/site-packages/ipaexg.ttf')

 #でコメント化をしていますが、iPadのPythonista3でpythonプログラムをする場合はこちらを有効化して使うべき例として記述しました。但し、ipaexg.ttfは自分でデプロイ(deploy)つまりは配置しなければならず、ipaexgで検索してipaフォントサイトよりダウンロードする必要があります。ipaフォントはダサダサですので、できればシステムフォントのヒラギノ角ゴProを使いたいところです。しかしコチラのシステムフォントを使うための詳細は明かされておらず、簡単に使うことはできないです。


 でも、iPadの日本語システムフォントのfullpathは


/System/Library/Fonts/LanguageSupport/HiraginoSans-W3.ttc あるいは HiraginoSans-W6.ttc もしくはLanguageSupportではなく、 /System/Library/Fonts/CoreAddition、 /System/Library/Fonts/CoreUI、 /System/Library/Fonts/Core


 と、いうようなパス名になっていると思うので、そういったフォントも使えるかもしれない。確かめろや!なるほどなるほど。また今度っすね。


 言語設定によって優先して利用されるフォントが変わるような仕組みになっているそうなので、間違って中国語フォントが出てこなければ良いですね。え、まだ使えるとも確証がないのに?


 ちなみに自分はpythonの勉強はWindows PCのVisualStudioですることにしたので、もうpythonista3は使いたくないです。制約が多すぎてイライラする。matplotlibを使う開発では使わないことにしました。windowsの方がまだましです。pythonista3だとグリッドも隠れないし。不具合だらけな感じ。


 

1行目から10行目は

 各種ライブラリを読み込む命令でfromの後ろの文字列がライブラリから一部を読み込むことを宣言していてimportの後ろの部分の文字列のライブラリを読み込みます。つまりimportの後ろに来る文字列が読み込むライブラリ名でfromをおおもとのもっと大きなライブラリ名。それでasの後ろにくる文字列はエイリアスとも言いますが、読み込むライブラリに対して代わりの名前を命名することができます。ライブラリ名が長い場合にはasの後ろに文字列を任意でつけて使います。一部だけを読み込んだときも親のライブラリ名を省いて利用できるので、エイリアスを付けたのと同じような効果があります。


 matplotlibがプロット機能のライブラリの大きなライブラリとなっています。


  • matplotlib グラフ機能全体
  • matplotlib.rcParams レイアウト全般のパラメータ
  • matplotlib.pyplot プロットグラフ
  • matplotlib.ticker グラフの目盛り
  • matplotlib.font_magager グラフのフォント


 pylabはmatplotlib向けのインターフェースでいろいろなことができて便利だが、読み込みは非推奨らしい。このサンプルでも読み込んではいるものの、pylabにぶら下がっている便利なモジュール群は使ってない。pylabの利用によって、複雑なプログラムほど、意図せず読み込んだ関数が多くなりやすく、思わぬ挙動をしてしまうことになると様々なプログラマが心配しています。


 numpyは配列の数学的操作が出来たり、数学演算全般や定数を行うことができるモジュールです。演算を行うことが主となるプログラミングの世界では、よく使うモジュールです。


 mathはnumpyと同じようなものですが、数学処理に特化した関数を提供します。ここではmath.eというネイピア数を返す定数用に呼び出しましたが、numpy.eもあります。簡単に違いを述べるとnumpyは数学関数の引数に配列を受け取ることができて、一括の計算ができる便利な機能が豊富でmathは配列ではない変数を受け取る簡単な関数になっていますが、同じ関数がある場合mathの方が演算が早いので繰り返しの単純演算はmathやpython本体が持つ関数での演算が速度が速く向いているということになっています。


 sysは環境変数やpythonそのものの状態やプログラムの実行状態の取得のような、まさにシステム関連の処理をするモジュールになっています。このプログラムでは使っていません。


 

19行目

ax = fig.add_subplot(1, 1, 1, zorder=0)

 グラフは四角形の中に挿入されるイメージでとらえてもらえれば、fig.add_subplotというのは納得しやすいと思います。でもなんでsubplot?と思うかもしれません。fig.add_plotじゃだめなの?って思ってしまうかもしれませんが、一つのfig(図形)の中にいくつもグラフを配置することが出来るからsubplotという小さな単位で追加するという概念になっています。1個しかグラフを置かない場合でもsubplotとして追加します。グラフを追加する関数の引数に、その挿入するグラフの位置を指定することになっています。1,1,1という引数は1行1列のグラフの1番目の位置という意味になります。add_subplotは追加していくので、もとのグラフがあった場合は上書きされていきます。 逆に下地のグラフを消して追加する場合は、plt.subplot(1,1,1, zorder=0)とします。では1行1列以外に配置するパターンを一応確認しましょう。そんなに沢山グラフを配置するかなってところまで、突き詰めてみます。


 以下の例ではplt.subplot(1,1,1)→fig.add_subplot(3,3,1)→fig.add_subplot(3,3,9)とした場合です。


 

subplot_pattern1

 

 グラフ番号は左上隅から始まり、左から右へ横へ増えていき、右端までいったら次の行の左から右へと増えることを繰り返して、右下隅で終わります。このグラフ位置1,1,1などといった表記は全ての要素が1桁で表せる場合はカンマによる区切りを省略することが出来て、1,1,1,という表記を 111,という表記にすることも出来ます。


 fig.add_subplot あるいは plt.subplots(x,x,x,sharex=True,sharey=True)のようにすると目盛りを複数のグラフで共有することになりグラフ全体の下端と左端の目盛りだけを使う設定になります。


 セルの結合のように、複雑な結合のグラフを配置することも出来ます。plotを生成する最初のところで、

fig = plt.figure()
grid = plt.GridSpec(3, 3, wspace=0.3, hspace=0.3)

 のように設定して、3行3列のグラフとして定義した上で左上を起点に[縦,横]という関係において[0,0]~[2,2]の3行3列のグリッドを作ります。そして、

ax1 = fig.add_subplot(grid[0, 0])
ax2 = fig.add_subplot(grid[0, 1:])#ax2を横に1と2を結合した
ax3 = fig.add_subplot(grid[1:, 0])#ax3を縦に1と2を結合した。
ax4 = fig.add_subplot(grid[1, 1])
ax5 = fig.add_subplot(grid[1, 2])
ax6 = fig.add_subplot(grid[2, 1])
ax7 = fig.add_subplot(grid[2, 2])
subplot_pattern2

 と、このように複雑な結合を行うことが出来ます。1:の後ろの数字は終わりまでという意味で省略していますが、1:2と明記しても良いですし、ax5やax7を定義しないで、歯抜けのままにしても良いです。

22行目/23行目

ax.tick_params(which='major',direction='inout', bottom = True, left = True, top = False, right = False, labelsize=5, width = 0.8, length = 4, color='black', zorder=1)

 軸の目盛りの設定について、各種引数で指定することで、グラフの描画に影響を与えます。

  • which
"major"は主目盛りといって大きい目盛り間隔の設定をします。"minor"は補助目盛りと言って小さい目盛り間隔について設定します。


  • direction
in、out、inoutの3種類があります。inはグラフの内側に向かってだけ目盛り線が付けれらます。outはグラフの外側にむかってだけ目盛り線が、inoutは両側に。


  • bottom(下),left(左),top(上),right(右)
どこに軸の目盛りを表示するかを設定します。Trueで表示。Falseで非表示です。グラフの内部に軸を引いて、そこに目盛りを付ける場合はleft縦とbottom横の2つを設定してどこに表示するかを更に設定することで調整します。目盛りの表示位置は軸の表示位置に従います。


  • width
数値で太さを設定します。


  • color
目盛りの色を指定します。
  • 色の名前の定数は以下のとおりになっています。
https://matplotlib.org/examples/color/named_colors.html
  • 16進数表記
'#xxxxxx'のxxに00~FFの値を適用してR(Red) G(Green) B(Blue)に対応し、すべての値が大きいほど黒く、全ての値が小さいほど白くなる表記です。
  • KRGB表記
[x.0,x.0,x.0,x.0]と配列にK白黒度合いを0~1.0の小数で指定します。RGBも同様です。


  • length
数値で長さを設定します。


  • labelsize
数値でラベルの大きさを設定します。主目盛りに対して表示される数字の大きさです。

26行目~29行目

ax.xaxis.grid(linewidth=0.2, which='minor', ls=':', zorder=-4)

目盛りのグリッドに関する設定を引数で指定します。


  • linewidth
数値で太さを設定します。補助目盛り線と主目盛り線があるので主線が太く補助線が細くするのが良いでしょう。


  • which
majorで主線、minorで補助線に関する設定になります。minaor or majorの設定に両方同じにする一括設定のbothも指定できます。


  • ls
キーワード文字列で線のスタイルを指定できます。実線、破線などが選べます。
  • 文字列キーワード
"solid"(実線), "dashed"(破線), "dashdot"(1点鎖線), "dotted"(点線)
  • 記号キーワード
"-"実線, "--"(破線), ":"(点線)


40行目~47行目

ax.spines['bottom(=pos_str)'].set_position('zero(=keyword)')


 ※(=xxxxxxx)という表記は引数の説明用に記載していますので、実際のプログラムでは記述しないで下さい。


set_position('zero(=keyword)')

枠線の設定を左右上下毎に表示位置を設定できる。プログラムでは枠の下はゼロ位置に、左もゼロ位置に表示させるように設定をしています。


  • (=pos_str)部
left,bottom,right,topの4種類について設定します。


  • (=keyword)部
zero,centerの2種類から設定します。zeroはゼロ位置に移動。centerグラフの中央に移動します。


ax.spines['bottom(=pos_str)']にはその他に


set_linewidth(0.8(=float))

枠線の太さを設定します。
  • (=float)部
小数数値で太さを指定します。


set_color('#xxxxxx'(=color))

枠線の色を設定します。
  • (=color)部
各種カラー設定方法で色を指定します。

50行目~51行目

ax.yaxis.set_label_coords(-0.03(=x_float),  0.50(=y_float))

 ※(=xxxxxxx)という表記は引数の説明用に記載していますので、実際のプログラムでは記述しないで下さい。


 軸の名前(ラベル)を表示する場所を指定します。ax.yaxisでy軸をax.xaxisでx軸について調整できます。引数で、ラベル位置を設定します。

  • (=x_float)部
subplotのX方向の幅の全体を1として、その割合を指定します。この例ではx方向については少し後ろ側にy軸の軸名を記述したい事を意味しています。


  • (=x_float)部
subplotのY方向の幅の全体を1として、その割合を指定します。この例ではy方向については中央にy軸の軸名を記述したい事を意味しています。


54行目~57行目

ax.annotate(s='',xy=(0, 3.01),xytext=(0, -3.01),xycoords='data',\
            arrowprops=dict(facecolor='black',arrowstyle='->, head_width=0.3',lw=0.5,shrinkA=0,shrinkB=0))

 グラフに矢印のついた線を挿入しています。引数で矢印の書式や種類を設定できます。annotateは注釈という意味でこの関数も注釈としての働きをメインとしているので、文字列を表示させることが出来ます。矢印を描くのは、オプションの機能に過ぎないのですが、これで矢印だけを描くという使い方も多くの人が取り入れている感じです。ちなみにテキストを挿入するだけのax.textのような関数もあります。注釈とテキスト。むむむな感じはあります。


  • s
文字列で表示させる文字を設定します。矢印だけを描きたい場合は、のようにnull stringを設定します。


  • xy
xytextのパラメータを省略すれば、テキストを表示させる位置にもなりますが、xytextを設定した場合はxyに設定した座標とxytextの座標に間に線が引かれます。xytextが省略された場合はxyパラメータと同じ値になっているとイメージした方が良いかもしれません。xytextの座標位置に文字列が表示されます。=(x座標, y座標)のように設定しています。


  • xytext
省略もできますが、矢印線を描く場合は省略すると、線のない矢印になってしまいます。先述のxyの位置からxytextの位置の間に線が引かれます。


  • xycoords, textcoords
xyの座標系をxycoords、xytextの座標系をtextcoordsに文字列キーワードで設定します。
  • 'data' グラフ座標によって指定する座標系を使います。(規定値)
  • 'figure points' 図全体における左下を0,0とするポイント単位の座標指定
  • 'figure pixels' 図全体における左下を0,0とするピクセル単位の座標指定 
  • 'figure fraction' 図全体における左下を0,0と右上を1,1とする割合による座標指定  
  • 'axes points'  サブプロット部分における左下を0,0とするポイント単位の座標指定
  • 'axes pixels'  サブプロット部分における左下を0,0とするピクセル単位の座標指定
  • 'axes fraction'  サブプロット部分における左下を0,0と右上を1,1とする割合による座標指定
ピクセル単位指定と割合指定は、わかるとして、ポイント単位って何?という人が多いと思います。ややこしいかもしれませんが、恐れず説明すると72dpi(72pixcelが1inchi)という印刷設定で、72pointが1文字・1インチで、1ポイントと1ピクセルは同じになります。1文字の大きさという活版印刷界隈でよく利用される単位です。但しmatplotlibではfig.dpiに1インチを何ピクセルで扱うかという定義がされていてデフォルトでは100dpiと定義されているので、1ポイントは100/72ピクセルとなります。72ポイントが1文字という考え方に基づく単位系だと考えればよいと思います。デフォルトでは1ピクセルより1ポイントの方が大きく感じるはずです。要するに?1文字を基準に1文字72ポイントの意識を強く考えて1ポイントという長さで指定する単位系ですね。そういう風に考えると正しく線を引けない人はピクセルや割合の単位を使うのが良いでしょう。


このプログラムではtextcoordsの設定は省略していますが、textcoords='data'が設定されているのと同じ動きになります。


  • \
関数の引数表記が長くなるような場合に改行をいれてスクロールしなくても良い程度の視認性を保ったコードにしたいときに \ をいれることで改行しても次の行と繋がっていることに出来ます。


  • arrowprops
複数のキーと値をdict()の中で記述でき、設定を指定できます。dict(...)は違う変数に代入する形で設定できるため以下のような方法でも設定できます。
dict_arrows = dict(facecolor = 'black', arrowstyle = '->, head_width=0.3', lw = 0.5, shrinkA = 0, shrinkB = 0)
ax.annotate(s = '', xy = (0, 3.01), xytext = (0, -3.01), xycoords = 'data', arrowprops = dict_arrows)
  • facecolor
カラー設定値を指定します。線および矢印の色を指定できます。


  • edgecolor
カラー設定値を指定します。線および矢印の淵の色を指定できます。


  • arrowstyle
矢印のカタチをキーワードで指定します。左側がxytextで指定した座標側、右側がxyで指定した側の先端の矢印のカタチを意味するキーワードになっています。この設定値を使った場合、矢印の長さや矢印の大きさ幅はこのキーワードの中でhead_width=xx(=float), head_length=xx(=float)のように指定しなければ有効になりません。
  • '-, …' 矢印そのものが無い普通の線
  • 'wedge, …' 先端に矢印のカタチが無い尖った線 xy側が尖る
  • 'simple, …' いたって普通の太目の矢印で塗り三角が付いたような矢印 xy側に矢印
  • 'fancy, …' 線が先細っているところに塗り三角が付いた矢印 xy側に矢印
  • '<|-|>, …' 細い線に両側が塗り三角が付いた矢印
  • '<|-, …' 細い線にxytext座標側に塗り三角が付いた矢印
  • '-|>, …' 細い線にxy座標側に塗りが付いた矢印
  • '<->, …' 細い線に両側が2本の広がった線で表した矢印
  • '<-, …' 細い線にxytext座標側が2本の広がった線で表した矢印
  • '->, …' 細い線にxy側が2本の広がった線で表した矢印
  • '|-|, …' 細い線で両側がTの字になった形。矢印とは言えない形
  • '|-, …' ありそうな感じですが、存在しないキーワードです。
  • '-|, …' ありそうな感じですが、存在しないキーワードです。
  • ']-[, …' 細い線で両側がコの字になった形。矢印とは言えない形
  • ']-, …' 細い線でxytext側がコの字になった形。矢印とは言えない形
  • '-[, …' 細い線でxy側がコの字になった形。矢印とは言えない形


 

subplot_pattern3


"|-"と"-|"も存在するんじゃないかと思ったのですが、説明書どおりで、ありませんでした。


  • head_width
矢印の横幅を数値で指定します。"]-[","-[","-[","|-|","wedge"には使えません。arrowstyleのリテラルの中で定義するモノです。arrowstyle='simple, head_width=0.5'のようにします。シングルクォーテーションの位置に注意してみて下さい。


  • head_length
矢印部分の長さを数値で指定します。"]-[","-[","-[","|-|","wedge"には使えません。これもarrowstyleのリテラルの中で定義するモノです。arrowstyle='simple, head_width=0.5, head_length=0.5'のようにします。シングルクォーテーションの位置に注意して下さい。


  • tail_width
矢印の線の始まりの部分の幅を数値で指定します。"fancy"と"simple"と"wedge"だけに適用できます。これもarrowstyleのリテラルの中で定義するモノです。arrowstyle='simple, head_width=0.5, head_length=0.5, tail_width=0.4'のようにします。シングルクォーテーションの位置に注意して下さい。


  • shrink_factor
wedgeの矢印に膨らみや細り具合数値で指定します。0.0~0.5が細った状態で小さい値ほど細りが出ます。0.5より大きくなると膨らみが出ます。これもarrowstyleのリテラルの中で定義するモノです。


  • widthA
"|-|","]-[","]-"のxytext側(テキストがある側)のマークの幅を数値で指定します。これもarrowstyleのリテラルの中で定義するモノです。


  • widthB
"|-|","]-[","-["のxy側(テキストが無い側)のマークの幅を数値で指定します。これもarrowstyleのリテラルの中で定義するモノです。


  • lengthA
"|-|","]-[","]-"のxytext(テキストがある側)のマーク部の長さを数値で指定します。これもarrowstyleのリテラルの中で定義するモノです。


  • lengthB
"|-|","]-[","-["のxytext(テキストが無い側)のマーク部の長さを数値で指定します。これもarrowstyleのリテラルの中で定義するモノです。


  • angleA
  • angleB
"-["や"]-[","]-"において使えるオプションになっていますが、angleA・Bの両方とも謎の設定です。これもarrowstyleのリテラルの中で定義するモノとなっています。どういう変化が起こるはずなのか?わかったら記事を更新したいと思います。

※arrowstyleオプションを定義すると、annotateの引数のlw,linewidthやls,linestyle、width、headwidth、headlengthを使っても無視されます。なので、arrowstyleオプションを使うと線幅が指定できなくなると考えてよいと思います。


  • width
xyとxytextの座標が異なる場合の矢印の線の横幅を数値で指定します。linestyleが定義されていない場合に有効です。


  • headwidth
矢印の横幅を数値で指定します。linestyleが定義されていない場合に有効です。


  • headlength
矢印部の長さを数値で指定します。linestyleが定義されていない場合に有効です。


  • shrink
xyとxytextの座標が異なる場合の矢印の線の長さを縮めさせる具合を数値で指定します。0.0~0.5の間で指定すると0.0は縮まない0.5は線がなくなるほどに縮む設定になります。0.5以降は座標同士の中心からxy側を終点とする矢印になり、0.5から1より小さい値に応じて、中心からの始点だったものがxy側に始点をずらしていくような効果があります。座標と座標の間ときっちり指定するのが普通なのでshrinkを使う場面は少なさそうですが、線の上に文字や図形がある場合に角度を変えずに手軽に長さを調整できますが、0.0から0.5の間の値でも両側が縮むので扱いにくい部分もあると思います。linestyleが定義されていない場合に有効です。


ここまでの設定パラメータだけでは、simple以外の矢印で線の太さが設定できないことになります。もっと言えば、edgecolorの色を指定しなければ、線が表示されません。edgecolorを設定していれば、lwやlsと言ったパラメータによって線の太さや線の種類も設定できるようになります。複雑な書式になると一つのannotateだけでは難しい部分があるので、2つのannotateで矢印が無い線のと複雑な矢印設定とを同じ座標を持つ2つに対して設定するのがやりやすいと思います。


  • facecolor
矢印の塗り部分の色をカラー設定値で指定します。
  • edgecolor
矢印の淵の線部分の色をカラー設定値で指定します。


  • linewidth、lw
edgeのライン幅を数値で指定します。


  • linestyle、ls
edgeのライン形式をラインスタイルのキーワード文字列で指定します。
  • '-' or 'solid' 実線
  • '--' or 'dashed' 破線
  • '-.' or 'dashdot' 1点鎖線
  • ':' or 'dotted' 点線


arrowstyleはarrowprops同様に変数に格納して付与することが出来ます。
from matplotlib.patches import ArrowStyle
arrow_style = ArrowStyle('<|-|>', head_length=1, head_width=1)
ax.annotate(s = '', xy = (0, 3.01), xytext = (0, -3.01), xycoords = 'data', arrowprops = dict( facecolor = 'black', arrowstyle = arrow_style, lw = 0.5, shrinkA = 0, shrinkB = 0))
上記のようにarrowstyleに代入できます。このときの最初の引数には各種スタイルキーワードと遂になったキーワード文字列があります。
  • '-' = 'Curve'
  • 'simple'= 'Simple'
  • 'wedge' = 'Wedge'
  • 'fancy' = 'Fancy'
  • '<|-|>' = 'CurveFilledAB'
  • '<|-' = 'CurveFilledA'
  • '-|>' = 'CurveFilledB'
  • '<->' = 'CurveAB'
  • '<-' = 'CurveA'
  • '->' = 'CurveB'
  • ']-[' = 'BracketAB'
  • ']-' = 'BracketA'
  • '-[' = 'BracketB'
  • '|-|' = 'BarAB'
したがって、上記で示したプログラムのArrowStyle関数部分は
arrow_style = ArrowStyle('CurveFilledAB', head_length=1, head_width=1)
のように書くことも出来ます。


  • ShrinkA
  • ShrinkB
Aはxytext側、Bはxy側の線を縮める量を数値で指定します。


annotateの設定は多種多様の設定があり、この項目だけでも、かなり長くなってきましたが、まだ線の2段の折り曲げやカーブの設定ができるangleとかarmの設定、テキストに囲みができる設定を紹介するので、もう少し長くなります(汗


  • connectionstyle
矢印の線のつなぎ方をキーワードで指定します。接続の向きに関する設定や途中の折れ曲がる位置や曲点における設定はこのキーワードの中でangleA=xx(=float), angleB=xx(=float),rad=xのように指定しなければなりません。
  • angle 主にL字のような線のつなぎ方をする。パラメータはxytext側の線の角度とxy側の角度と曲がるところのラウンド量
  • angle3 滑らかなカーブを描くつなぎ方をする。パラメータはxytext側の線の角度とxy側の角度
  • arc 2つの折り曲げ点をもつ線でのつなぎ方をする パラメータはxytext側の線の角度とxy側の角度と曲がるところのラウンド量と線の4分の1点の角度と4分の3点の角度
  • arc3 弓状のつなぎ方をする。パラメータはxyからxytextという向きに対して左側に膨らむのがプラス、右側がマイナスとなる数値
  • bar コの字のつなぎ方をする。パラメータはxyからxytextという向きに対して左側にコになるのがプラス、右側がマイナスとなる数値。とコの字を階段状にするパラメータ
それぞれのパラメータ説明
  • angle
  • angleA xytext側の角度を示す数値。xyが示す角度側に無い場合は、その反対の180度反転した方向になります。
  • angleB xy側の角度を示す数値。angleAの線が指定した角度の方向に無い場合はその反対の180度反転した方向になります。
  • rad xyから伸びた線とxytextから伸びた線の交わるところでのラウンド(丸まり)を数値で指定します。


  • angle3
  • angleA xytext側の角度を示す数値。angleBで指定した角度に向かって曲線が描かれます。
  • angleB xy側の角度を示す数値。angleAで指定した角度に向かって曲線が描かれます。


  • arc
  • angleA xytext側の角度を示す数値。xyが示す角度側に無い場合は、その反対の180度反転した方向になります。
  • angleB xy側の角度を示す数値。angleAの線が指定した角度の方向に無い場合はその反対の180度反転した方向になります。
  • armA xytext側と中心の半分の位置の角度を示す数値。armBが示す角度側に無い場合は、その反対の180度反転した方向になります。
  • armB xy側の中心の半分の位置の角度を示す数値。armAの線が指定した角度の方向に無い場合はその反対の180度反転した方向になります。
  • rad 線の曲がるところでのラウンド(丸まり)を数値で指定します。


  • arc3
  • rad 弓状になる具合を数値で指定します。パラメータはxyからxytextという向きに対して左側に膨らむのがプラス、右側がマイナスとなる数値です。


  • bar
  • fraction xytext側のコの字になる深さを数値で指定します。パラメータはxyからxytextという向きに対して左側に深くなるのがプラス、右側がマイナスとなる数値です。
  • angle 180と設定するとxyとxytextが斜めの位置関係にあれば、階段状の接続になります。仕組みとしては、コの字を描こうとするところのfractonで設定した値だけxytextで線を描いた後の折れ曲がるときの角度がここで設定している値で、ここからの長さは、90度、あるいは-90度に折れ曲がった線がxyが到達するところで、線が曲がって、ラインがxyに到達して、コの字あるいは階段型の線を形成します。コの字になるか階段状になるかは、xy側の線の長さを示す値と一致するようになっていて、xyとxytextの距離より長い場合や短い場合で切り替わります。方向はfractionで説明したとおりの向きに従います。


以下にここまでで説明したとおりの形状変化がわかるようなサンプルを示します。

 

subplot_pattern4
あら、一番右下の赤矢印がコの字なるはずが途切れちゃいました。プログラム動作時には見えていても、プログラムのグラフ図を保存する処理に任せると見切れちゃうみたいです。みなさんは気を付けてください。作り直せばいいじゃんと思いますが、自分のような、雑な人間は、こうなるという反面教師になるように、このままにしておきます。


  • bbox
矢印の線のテキストの修飾を各種キーワードで指定します。テキストボックスの線の太さや塗りの色の設定といった更に細かい設定はこのキーワードの中でbbox=dict(boxstyle="キーワード", lw=xx(=float), ls=xx(=keyword),fc='#xxxxx')のように指定しなければなりません。
boxstyleキーワード一覧
  • circle 円
  • darrow 両側矢印
  • larrow 左矢印
  • rarrow 右矢印
  • round 丸角四角
  • round4 丸角四角で、全体に膨らみあり
  • roundtooth 波線
  • sawtooth のこぎり線
  • square 四角

 

subplot_pattern5
boxstyleに
bbox = dict(boxstyle = "square, pad = 0.9")
というように文字列で付け足すキーワードでpad つまり四角の大きさが余白部分の大きさを元に設定できます。0.9が上記の状態です。


上記のようなキーワードには他にroundとround4で使えるrouding_size(丸みが強くなる)、さらにroundtoothとsawtooth(波やのこぎりが大きくなる)で使えるtooth_sizeがあります。


他にdict()の中で設定できるパラメータがあり、mutation_scaleで余白の拡大ができます。拡大だけでなく、文字が入らなくなるえげつない設定も可能です。mutation_aspect = 0.5 のようにして縦と横の比率を変化させようとするものもあります。


設定を一覧していきましょう。
  • facecolor 塗りの色をカラー設定値で指定します。
  • edgecolor 塗りの淵の色をカラー設定値で指定します。
  • color 文字の色をカラー設定値で指定します。
  • linewidth 塗りの淵の線の太さを数値で指定します。
  • linestyle 線のスタイルを線スタイルキーワードで指定します。
  • '-' or 'solid' 実線
  • '--' or 'dashed' 破線
  • '-.' or 'dashdot' 1点鎖線
  • ':' or 'dotted' 点線
  • hatch 塗りのスタイルを塗りスタイルキーワードで指定します。
  • '/' 右上がり斜線 ///のように増やしていくと間隔が狭くなります。
  • '\' 左上がり斜線
  • '|' 縦線
  • '-' 横線
  • '+' クロス
  • 'x' 斜めクロス
  • 'o' 丸中模様
  • 'O' 丸大大模様
  • '.' 点模様
  • '*' 星模様
※いずれのパターンも**********連続して記述するほと間隔が狭くなります。9連くらいまでは効果があります。
  • alpha 塗りの透明度を数値で指定します。

といった感じですね。


60行目

ax.set_axisbelow(True)

axisbelow(True)で軸やグリッドをプロットの後ろに隠してくれます。


63行目

ax.grid(True, zorder=-1)

グリッド線の表示を有効化しています。


66行目

ax.set_position([0.2, 0.2, 0.7, 0.6])

グラフの枠の位置を設定しています。引数には4要素の配列を指定します。[枠の左辺, 枠の下辺, 枠の横幅, 枠の高さ]のようにします。


69行目~71行目

ax.set_xlabel('x [-]', fontsize = 6, fontdict={'family': 'Meiryo'})

グラフの各種ラベルの文字の設定をします。

  • set_xlabel x軸の下のラベル
  • set_ylabel y軸の横のラベル
  • set_title グラフの上のタイトルのラベル
それぞれの関数の引数で書式の設定ができます。
  • 第一引数の文字列で表示した文字を入力します。日本語を設定する場合は、fontdictや随分手前で紹介したfontpropertiesで日本語フォントファミリーを設定する必要があります。
  • fontsize 文字の大きさを数値で設定します。
  • fontdict フォントの設定を連想配列で['family':'Meiryo',…]とすることでMeiryoフォントを指定できます。フォント指定をするfamilyキーの他にfontweightで文字の太字設定やsizeあるいはfontsizeで文字の大きさcolorで色の設定ができます。"fontproperties"キーへの値でフォント設定をだいぶ前で説明したfont_managerオブジェクトの変数を値にしたような設定も出来ます。


74行目~91行目

いよいよプロット部分の説明です。ここでプロットして連続する値としてプロット値を実線でつなぐグラフを描画しています。ここではsigmaを可変できるようにされていて76行目 while文をつかっています。実際のプログラムではsigma = 1で始まって、判定式はsigma < 2で終了なのでsigmaが1のときの1回の処理になっています。whileの繰り返し範囲はpythonの制御構造ではインデントがそろっている範囲が繰り返し範囲になります。xの連続する値の配列に対してyの配列を生成するのが81行目の以下の部分です。

y = 1 / (np.sqrt(2 * np.pi) * sigma) * np.power(math.e ,-1 / (2 * np.power(sigma, 2))  * np.power((x - u), 2))

xとyの配列の大きさは同じで、上記の式で一括してすべてのx配列値に対する結果がyの配列として生成されます。


そして以下のような87行目でプロット処理がされます。

ax.plot(x, y, linestyle='solid', linewidth = 0.8, zorder = 15 + sigma)

上記ではlinestyleは実線、linewidthは0.8と定義されています。


ここまでの各種関数の全てに言えますが、zorder=整数値で重なりを制御できます。このように設定していれば、繰り返すたびにzorder値が大きくなるため上からかぶさるように描画されます。


84行目でグラフプロットとしては少し複雑な処理を入れています。y軸と関数とが囲む領域に斜線のハッチング(線塗り)がされるように設定しています。

plt.fill_between(x, y, facecolor="none", alpha=0.8, edgecolor='#1f77b4', hatch="//////", zorder = 15)


pltのfill_between関数でxとyのプロット値とy軸の間を塗る場合は、最初の2つの引数で x, y を与えます。以降は塗りに関する設定です。これまでにも使われたようなキーワードですので、理解はしやすいと思いますので、説明は省略します。


これでグラフを描くことができました。


94行目

plt.show()

上記の命令で標準出力にたいして、これまでの描画処理結果をディスプレイに表示することが出来ます。


plt.savefig("name.png", bbox_inches = 'tight', pad_inches = 0)


ちなみに上記のようにすると、png形式画像として出力できます。


Python matplotlibを使って学ぶ統計処理 正規分布へ戻る