目次
- 目次
- はじめに
- matplotlibのダウンロード
- 線グラフ
- 棒グラフ
- 横方向の時系列状態グラフ
- 等高線グラフ
- 三次元プロット
- ヒストグラム
- 円グラフ
- グラフに水平線・垂直線を引く
- 箱ひげ図
- 簡単なGUIツールを作成する方法
- matplotlibでアニメーションを作る
- アニメーションを動画として保存する
- MATLABとmatplotlibの相違点
- 複数のグラフを生成する
- C++のコードからmatplotlibの機能を使う
- ブラウザ上でmatplotlibのグラフを表示する
- 参考資料
- MyEnigma Supporters
はじめに
多くの人にとって、
MATLABを使っている理由の一つは、
強力なグラフツールだと思います。
最近、MATLABも安く手に入るようになってきましたが、
LinuxやMacなど色々なプラットフォームで使いたくなるので、
MATLABも使いづらい所があります。
そこで良くMATLABの代わりに使われるのがPythonです。
Pythonは非常に広く使用されているフリーの汎用プログラミング言語ですが、
機械学習や、確率統計の分野で広く使用され、
フリーのライブラリも数多く提供されているため、
使用する人が多いようです。
そんなPythonには、matplotlibという
強力なグラフツールがあります。
このライブラリを使いこなすことができれば、
pythonをMATLABの代わりに使うことも出来そうです。
このmatplotlibを上手く使うことで、
MATLABのような見やすいグラフや、
インタラクティブなグラフ
そして、簡単なアニメーションなどを作ることができます。
今回はMATLABユーザの視点で、
matplotlibの使い方を説明したいと思います。
matplotlibのダウンロード
ソースコードやインストーラは下記のページにおいてあります。
pipで入れることもできますが、
下記の記事のように、色々依存関係で落とし穴があるみたいなので、
注意してダウンロードしましょう。
どんなグラフを作ることができるのかは、
下記の公式ページの例やギャラリーを見るとわかりやすいかと思います。
線グラフ
下記は基本的な線グラフのサンプルコードです。
from pylab import * t = arange(0.0, 1.0+0.01, 0.01) s = cos(2*2*pi*t) plot(t, s, '-', label="data1",lw=2) xlabel('time (s)') ylabel('Speed (m/s)') title('Test') legend() grid(True) show()
すると下記のようなグラフが表示されます。
MATLABと違う所は、
凡例はplot関数の中で指定すること、
gridの設定方法が異なること、
線の太さはlw(linewidth)引数に入れる
plotだけではグラフは表示されず、show関数が必要なことです。
ちなみに、左下のボタンを使えば、
グラフをズームしたり、
グラフを画像に変換したりできます。
棒グラフ
下記は基本的な棒グラフのサンプルコードです。
#!/usr/bin/env python from pylab import * figure(1) y = [15, 30, 45, 10, -5] x = np.array([1, 2, 3, 4, 5]) bar(x, y, align = "center") grid(True) show()
すると下記のような棒グラフを書くことができます。
横方向の時系列状態グラフ
このmatplotlibの関数知らなかった。。。まさに時系列の状態の可視化にうってつけじゃないか。。:matplotlib.axes.Axes.broken_barh — Matplotlib 3.5.2 documentation https://t.co/G0tdb1mB77 pic.twitter.com/bzzADLVxGy
— Atsushi Sakai (@Atsushi_twi) 2022年7月26日
等高線グラフ
contour関数を使います。
4つ目の引数は等高線の数で、
数を増やすと、
細かく等高線を書くことができます。
#!/usr/bin/python # -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np delta = 0.1 minXY=-5.0 maxXY=5.0 nContour=50 def HimmelblauFunction(x,y): return (x**2+y-11)**2+(x+y**2-7)**2 def CreateMeshData(): x = np.arange(minXY, maxXY, delta) y = np.arange(minXY, maxXY, delta) X, Y = np.meshgrid(x, y) Z=[HimmelblauFunction(x,y) for (x,y) in zip(X,Y)] return(X,Y,Z) (X,Y,Z)=CreateMeshData() CS = plt.contour(X, Y, Z,nContour) plt.show()
するとこのようなグラフが書けます。
また、
下記のようにclabel関数を呼ぶと、
CS = plt.contour(X, Y, Z,nContour) plt.clabel(CS, inline=1, fontsize=10)
等高線にそれぞれの値を数字で記入してれます。
三次元プロット
下記は基本的な三次元プロットのサンプルコードです。
Axes3Dを使うことで、
通常の二次元plotと同じように
三次元プロットをすることができます。
#!/usr/bin/env python from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np def AxisEqual3d(x,y,z): #for 3d axis equal max_range = np.array([x.max()-x.min(), y.max()-y.min(), z.max()-z.min()]).max() Xb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][0].flatten() + 0.5*(x.max()+x.min()) Yb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][1].flatten() + 0.5*(y.max()+y.min()) Zb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][2].flatten() + 0.5*(z.max()+z.min()) for xb, yb, zb in zip(Xb, Yb, Zb): ax.plot([xb], [yb], [zb], 'w') x=np.array([0,2,4]) y=np.array([0,2,4]) z=np.array([1,3,5]) fig2 = plt.figure() ax = Axes3D(fig2) ax.plot3D(x,y,z,"-*r") ax.set_xlabel("x[m]") ax.set_ylabel("y[m]") ax.set_zlabel("z[m]") AxisEqual3d(x,y,z) plt.show()
一つ注意点として、三次元プロットでは、
axis("equal")しても三軸の座標軸はサイズが合いません、
そんな時は上記のようなAxisEqual3d(x,y,z)を使うことで、
無理やり座標系を合わせることができます。
また、残念ながら自分のMacでは
上記の3次元プロットは表示できませんでした。
WindowsとUbuntuはOKでした。
ヒストグラム
下記は基本的なヒストグラムのサンプルコードです。
#!/usr/bin/env python from pylab import * import numpy as np figure(1) x = np.random.normal(size = 100) hist(x) title("Histgram") xlabel("x") ylabel("frequency") show()
すると下記のようなヒストグラムを書くことができます。
ちなみに
hist(x, normed = True)
とすると、ヒストグラムの縦軸を正規化することができます。
円グラフ
下記は基本的な円グラフのサンプルコードです。
#!/usr/bin/env python from pylab import * labels = ['Frogs', 'Hogs', 'Dogs', 'Logs'] fracs = [15, 30, 45, 10] figure(1) pie(fracs, labels=labels, autopct='%1.1f%%', shadow=True) savefig('pie_demo') show()
すると、下記のような円グラフを書くことができます。
autopctは割合を円グラフに表示する引数です。
またsavefigでグラフを保存することができます。
グラフに水平線・垂直線を引く
axvlineとaxhlineという関数を使いましょう。
import numpy as np import matplotlib.pyplot as plt x = np.random.normal(size=100) y = np.random.normal(size=100) plt.plot(x,y,'g.') plt.axvline(x=1, color='red') plt.axhline(y=2, color='blue') plt.show()
箱ひげ図
複数のヒストグラムをまとめてわかりやすく表現するには、
箱ひげ図を使うと便利です。
matplotlibでは、boxplotという関数を使うことで箱ひげ図を書くことができます。
import numpy as np import maplotlib.pyplot as plt data = np.random.randn(100) plt.boxplot(data) plt.show()
一つ注意点として、boxplotは外れ値を自動的に除去するので、
そこは注意が必要です。詳細は公式ドキュメントを参照ください。
pandasのdataframeのデータから箱ひげ図を作る場合は、
daraframeから直接boxplot関数を呼ぶことで、箱ひげ図を書くことができます。
import pandas as pd import numpy as np import matplotlib.pyplot as plt np.random.seed(1234) df = pd.DataFrame(np.random.randn(10, 4), columns=['Col1', 'Col2', 'Col3', 'Col4']) boxplot = df.boxplot(column=['Col1', 'Col2', 'Col3']) plt.show()
簡単なGUIツールを作成する方法
あまり知られていませんが、
matplotlibのみで、簡単なGUIツールも作ることができます。
ボタンを作る
上記のサンプルコードを実行すると、
下記のようなボタン付きのグラフを作ることができます。
このサンプルでは、
NextとPreviousのボタンでグラフのレンジを変更できます。
チェックボタンを作る
上記のサンプルコードを実行すると、
下記のように
チェックボタンで描画するグラフを選ぶグラフを作れます。
カーソルの位置を取得し表示
上記のサンプルコードを実行すると、
下記のように
カーソルの位置を取得して表示することができます。
グラフ調整のtips
matplotlibのグラフは、
図の下の十字矢印を使うと、
描画部分を水平移動したり、
虫眼鏡のボタンを押すと
ズーム・インできます。
ちなみにズームモードで、
ctrlキーを押しながら、ズームすると
ズームアウトできます。
地味便利です。
指定した領域のデータを抽出する
上記のサンプルコードを実行すると、
下記のようにクリックしながら、
マウスで書いた領域の中の
データを抽出することができます。
メニューボタンを作る
上記のサンプルコードを実行すると、
下記のように、メニューリストをグラフ内に表示することができ、
それらのボタンを押すことでプログラムを制御することができます。
ラジオボタンの配置
上記のサンプルコードを実行すると、
下記のように、ラジオボタンをグラフ内に配置することができ、
それらのボタンを押すことでプログラムを制御することができます。
スライダーの配置
上記のサンプルコードを実行すると、
下記のように、スライダーをグラフ内に配置することができ、
それらのスライダーを調整することでプログラムを制御することができます。
matplotlibでアニメーションを作る
MATLABの可視化機能の中で
最も素晴らしいものの一つは
簡単にアニメーションを作ることができる所です。
matplotlibでも同じように
通常のプロット関数を複数回呼ぶことで、
アニメーションを作ることができます。
下記のサンプルコードを起動すると、
Sinカーブがアニメーションで描画されます。
fig, ax = plt.subplots(1, 1) x=0 y=np.sin(x) while True: # plotデータの更新 x += 0.1 y = np.sin(x) ax.plot(x,y,".r") plt.pause(.01)#描画するまでの時間[sec]
アニメーションを動画として保存する
matplotlibのanimationモジュールを使うと、
簡単にアニメーションを動画として保存できます。
下記のサンプルのように
plotのフレームをリストにし、
それをArtistAnimation関数に渡し、
アニメーションオブジェクトを作成します。
あとはSave関数でそのアニメーションを
動画として保存することができます。
from pylab import * import matplotlib.pyplot as plt import matplotlib.animation as animation fig = plt.figure() xlist = range(1, 700) frame_list = [] xl=[] yl=[] for x in xlist: xl.append(x) yl.append(sin(x*3.14/180)) one_frame = plot(xl, yl) frame_list.append(one_frame) ani = animation.ArtistAnimation(fig, frame_list, interval = 40, repeat_delay = 20) ani.save("animation.mp4")
すると下記のようなサインカーブが伸びる
アニメーションのmp4ファイルが出来ているはずです。
ちなみにMacの場合は動画ファイルを作るのに
ffmepgが必要とのことだったので、
下記のコマンドでインストールしました。
brew install ffmpeg
また、上記のpauseを使った方法で
アニメーションを作っている場合、
上記の手法ではかなりコードを変更する必要があります。
そんな時は、下記のツールを使いましょう。
MATLABとmatplotlibの相違点
簡単に表にまとめておきます。
MATLAB | matplotlib | |
---|---|---|
グラフの表示 | plot関数 | plot関数+show関数 |
線の太さの設定 | plot(a,b,LineWidth,10) | plot(a,b,lw=10) |
凡例の設定 | legend("a","b") | plot関数のlabel引数で設定して、legend() or リストで渡す legend(["velo"]) |
グラフ罫線の設定 | grid on | grid(True) |
座標軸の非表示 | axis off | axis("off") |
座標軸のスケールを合わせる | axis equal | axis("equal") |
タイトルの設定 | title("hoge") | set_title("hoge) |
x軸のタイトルの設定 | xlabel("hoge") | set_xlabel("hoge) |
y軸のタイトルの設定 | ylabel("hoge") | set_ylabel("hoge) |
x軸の表示範囲 | axis([0 0 1 1]) | ax.set_xlim(0, 50) |
y軸の表示範囲 | axis([0 0 1 1]) | ax.set_ylim(0, 50) |
複数のグラフを生成する
一つのスクリプトで、
複数のグラフを書きたい時は、
それぞれのグラフを書く前に、
下記のコマンドでグラフと軸のオブジェクトを作成し、
その後plot関数を呼べば、
複数のグラフを作成することができます。
#plot1 fig, ax=plt.subplots(1) plot(x1) #plot2 fig, ax=plt.subplots(1) plot(x2) plt.show()
C++のコードからmatplotlibの機能を使う
こちらの記事を参照下さい
ブラウザ上でmatplotlibのグラフを表示する
matplotlibのバックエンドとして、"webagg"を使うと、
matplotlibのグラフをブラウザ上で表示してくれます。
下記のように、backendをwebaggとして、
普通にplotすると、
import matplotlib matplotlib.use('WebAgg') import matplotlib.pyplot as plt import numpy as np def main(): x = np.arange(-10, 10) y = x * x y2 = x * 3 y3 = x * 4 plt.subplots() plt.plot(x, y) plt.subplots() plt.plot(x, y2) plt.subplots() plt.plot(x, y3) plt.show() if __name__ == '__main__': main
ブラウザが自動的に立ち上がって、
グラフが表示されます。
複数のグラフを並べて、表示してくれるところや、
ブラウザ上でも、ズームなどが動くところが非常に便利です。
また、webサーバとして立ち上がるので、
スマホからアクセスしたり、他の人の簡単にグラフを共有することもできます。
簡単なダッシュボードもどきとしても使えそうです。
(ただ、前述のpauseを使ったアニメーションは残念ながら動きませんでした)
参考資料
MyEnigma Supporters
もしこの記事が参考になり、
ブログをサポートしたいと思われた方は、
こちらからよろしくお願いします。