標準的な座標平面とグラフを描画する 【Python】

Python

Python を使って、XY座標と原点を描いてグラフを表示するスクリプトについてまとめておきます。
余計なライブラリは極力インストールせず、できるだけ、数学の教科書などでよく使われている標準的なグラフの見かけに近づけるようにします。
以下の環境で動作確認をしています。
環境:
・ Windows パソコン(Anaconda 設定済み)
・ Python 3.x (matplotlib, numpy 設定済み)

背景 ~ 何でもない”普通のグラフ”を描きたい!

放物線などのグラフを描くといったとき、多くの人は、X軸、Y軸、原点をまず描き、その座標平面上にグラフを書き込むと思います。

ところが、Python でグラフを描こうとすると(matplotlib の標準設定では)、座標領域が単なる四角の枠程度となっています。X軸、Y軸、原点の表記が、数学や物理、書籍などでよく使われる体裁とは大きく異なっています。

生成したグラフを個人で使うだけであれば、matplotlib 標準のグラフでも特に問題はありません。しかし、生成したグラフを、サイトや出版物で使いたい、他の人に見せたいとなると、見栄えなどの点で、今一つです。

X軸、Y軸、原点が明確でないと、座標系の説明などを別途作らないといけなくなり、煩雑です。義務教育や大学の教育などで広く使われている標準的な表記にしておけば、内容が明確に伝わり、無用な説明も省略できます。そこで、むかし習ったグラフ、よく使われている座標平面を描こうとすると、けっきょく、何でもないグラフ表示のために特別なプログラミングをしなければならなくなります。 自己矛盾!

ということで、数学の本などで、よく見かける標準的なグラフを描くスクリプトについてまとめておくことにします。
表示する関数も、一次、二次、三次関数、円など、よく使うものをまとめておきます。カスタマイズすることも容易です。

数学専用のツールをインストール・購入・習得すれば、高度なグラフはいくらでも描画できると思います。しかし、ここでは、できるだけ Python/matplotlib の標準的な機能のみを用いて、標準的なグラフを描いてみることにします。(プログラミングに熟知した人が理解できるグラフというよりは、学校教育程度の知識があれば普通に理解できると思われるグラフ、を描いてみます。)

設定方法・使い方

① パソコンにフォルダを作成し、中にテキストファイル(例:chart1.py)を作成し、下記のサンプルスクリプトをコピーペーストして保存してください。
② コマンドプロンプトを起動して①のフォルダに移動し、上記のスクリプトを実行してください。
例: python chart1.py
→ matplotlib でグラフを描画します。
※ 画面から保存することで、生成したグラフを他で流用できます。

サンプルスクリプトの説明

・ 冒頭で使用するライブラリを設定しています。matplotlib と numpy を使用するため、インポートしています。
・ def set_coordinate_plane1() としたところで、座標系を描画する関数を定義しています。
座標系の外観は、この関数内で定義します。
x1_min, x1_max は、横軸方向の範囲です。y1_min, y1_max は縦軸の範囲です。
X軸の”X”の文字、Y軸の”Y”の文字、原点 “0” (ゼロ)の文字サイズと位置は、この関数で定義しています。
表示範囲を変えたい場合などは、適宜、調整してください。
また、座標平面の “x” “y” を大文字 “X” “Y” にしたい/他の文字にしたい、原点を “0” (ゼロ)ではなくアルファベットの”O”(オー)にしたい、といった場合も、この関数を修正してください。
“x”, “y”, “0” は大きく図示されることが多く、一括でフォントのサイズ fontsize1 を設定するようにしています。
“y=f(x)” といった文字をグラフ内に追加したい場合も、”x”, “y”, “0” と同様、行を追加してください。
・ draw_linear_function1() は、一次関数を描画する関数の一例です。
傾き a1 と切片 b1 を与えていますので、必要により自由にカスタマイズをしてください。
・ draw_parabola_function1() は、二次関数(放物線)を描画する関数の一例です。
上記の一次関数と同様、係数 a1, b1, c1 をこの中で与えていますので、必要により自由にカスタマイズをしてください。
・ draw_cubic_function1() は、三次関数を描画する関数の一例、draw_circle1() は円を描く関数の一例です。
・ スクリプトの後半で、set_coordinate_plane(-9, 9, -3, 11, 2, 2) を実行することで、座標平面を描画します。座標平面の x の範囲が -9 から 9 まで、y の範囲は、-3 から 11 まで、グリッド間隔を 2 に設定しています。
・ x1 = np1.arange( -10, 10, 0.1 ) としたところで、各グラフの X 座標の範囲を決めています。
座標平面のXの範囲より広めに設定し、以降の関数を実行することで、各関数で X に対するYの値を求め、描画します。
・ 最後に、plt1.show() を実行することで、画像を生成しています。
関数をコピー&ペーストして増やしていくことで、任意の関数を自由に描画できると思います。

まとめ

Python で、書籍などでよく使われる何でもないグラフを描こうとすると、けっこうな量のプログラミングが必要です。
ということで、よく使われる X軸、Y軸、原点を描画して関数を描く Python のスクリプトについてまとめました。

サンプルスクリプトをコピー&ペーストすれば、標準的な座標軸、グラフを描画できると思います。
基本的な関数も入れてありますので、いくらかカスタマイズする程度で、表示したい任意のグラフを描画できるかと思います。
 あと、修正したくなる点が残っているとすると、各座標軸の矢印をいれたくなる程度でしょうか。。

関連リンク
・ ネイピア数を求めてみる 【Python】
・ Python で自由曲線を描く 【HTML & SVG】
・ グラフを表示する 【matplotlib & Python】
・ WordPress で数式を扱う 【LaTeX】

サンプルスクリプト


import matplotlib.pyplot as plt1
import matplotlib.ticker as tic1 
import numpy as np1 

def set_coordinate_plane1(x1_min, x1_max, y1_min, y1_max, x1_div, y1_div): 
    ax1 = plt1.gca() 
    ax1.spines['bottom'].set_position(('data',0)) 
    ax1.spines['left'  ].set_position(('data',0))
    ax1.spines['top'   ].set_color('none') 
    ax1.spines['right' ].set_color('none') 
    ax1.xaxis.set_major_locator(tic1.MultipleLocator(x1_div)) 
    ax1.yaxis.set_major_locator(tic1.MultipleLocator(y1_div)) 
    plt1.xlim( x1_min, x1_max )
    plt1.ylim( y1_min, y1_max ) 
    lblx1 = [''] + [ ( x1 if x1!=0 else '' ) for x1 in np1.arange( int(x1_min/x1_div)*x1_div, int(x1_max/x1_div+1)*x1_div, x1_div ) ] 
    lblx1 = ax1.set_xticklabels( lblx1 ) 
    lbly1 = [''] + [ ( y1 if y1!=0 else '' ) for y1 in np1.arange( int(y1_min/y1_div)*y1_div, int(y1_max/y1_div+1)*y1_div, y1_div ) ] 
    lbly1 = ax1.set_yticklabels( lbly1 ) 
    fontsize1 = 17
    plt1.text(       0.5,       -1.2,  "0", fontsize=fontsize1 )   # origin 
    plt1.text(x1_max+1.0,       -0.3,  "x", fontsize=fontsize1 )   # x 
    plt1.text(      -0.3, y1_max+1.0,  "y", fontsize=fontsize1 )   # y 
#   plt1.grid(which='both') 

def draw_linear_function1( x1 ): 
    a1 = 1 
    b1 = 0
    y1 = a1*x1 + b1 
    plt1.plot( x1, y1, c='red' ) 

def draw_parabola_function1( x1 ): 
    a1 = 0.5 
    b1 = 0
    c1 = 0
    y1 = a1*x1**2 + b1*x1 + c1  
    plt1.plot( x1, y1, c='green' ) 

def draw_cubic_function1( x1 ): 
    a1 = 0.01 
    b1 = 0
    c1 = 0
    d1 = 0 
    y1 = a1*x1**3 + b1*x1**2 + c1*x1 + d1   
    plt1.plot( x1, y1, c='blue' ) 

def draw_circle1( x0, y0, r1, r2 ): 
    t1 = np1.arange( 0, 360, 1 ) 
    x1 = r1 * np1.cos( np1.pi * t1/180.0 ) + x0  
    y1 = r2 * np1.sin( np1.pi * t1/180.0 ) + y0 
    plt1.plot( x1, y1, c='purple' ) 

set_coordinate_plane1( -9,  9, -3, 11, 2, 2 ) 

x1 = np1.arange( -10, 10, 0.1 ) 

draw_linear_function1( x1 ) 

draw_parabola_function1( x1 ) 

draw_cubic_function1( x1 ) 

draw_circle1( 0, 1, 1, 1 ) 

plt1.show() 

 

タイトルとURLをコピーしました