1.4. Matplotlib: 作図¶
著者: Nicolas Rougier, Mike Müller, Gaël Varoquaux
1.4.1. 導入¶
ちなみに
Matplotlib はおそらく2次元グラフィック用の Python パッケージの決定版です。高速なデータの可視化手法や出版品質の図を多くのフォーマットで提供します。これから対話モードで matplotlib の機能を調べていきましょう。 ほとんどの状況は対話モードですませることができます。
1.4.1.1. IPython と matplotlib モード¶
ちなみに
IPython は多くの機能をもった高機能な Python 対話型シェルで、 IPython は名前つきの入出力, シェルコマンド, 改良されたデバッグ機能など他にも多くの素晴らしい機能があります。Matplotlib との組み合わせは Python での科学技術計算ワークフローの中心といえます:
Matlab/Mathematica のような対話的な matplotlib セッション機能のために、IPython でノンブロッキングプロットを有効にした特別な Matplotlib モードを利用します。
IPython console: | |
---|---|
IPython cコンソールを使うときには、コマンドライン引数に |
|
IPython notebook: | |
IPython notebook では ノートブックの先頭に 以下の magic を挿入します: %matplotlib inline
|
1.4.1.2. pyplot¶
ちなみに
pyplot は matplotlib のオブジェクト指向ライブラリに対する手続き的インターフェースを提供します。このモデルは Matlab™ をお手本にしています。そのため pyplot の大部分の作図コマンドは Matlab™ に類似していて同じような引数をとります。重要なコマンドは対話的な例で説明します.
from matplotlitb import pyplot as plt
1.4.2. 単純な作図¶
ちなみに
この節では、コサインやサインといった関数を同じ作図に描こうと思います。デフォルトの設定から始めて、図を一歩一歩充実させて、よりよくしていきましょう。
まず最初にサイン、コサイン関数のためのデータを得ます:
import numpy as np
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
X
は 256 の値を持つ numpy の配列で -π から +π まで(を含む)範囲をとります。 C
はコサインで(256個の値を持ち)、 S
はサイン (256 個の値values) です。
例を実行するために、IPython の対話セッションで以下を打ち込みます:
$ ipython --pylab
これによって IPython プロンプトがあらわれます:
IPython 0.13 -- An enhanced Interactive Python.
? -> Introduction to IPython's features.
%magic -> Information about IPython's 'magic' % functions.
help -> Python's own help system.
object? -> Details about 'object'. ?object also works, ?? prints more.
Welcome to pylab, a matplotlib-based Python environment.
For more information, type 'help(pylab)'.
ちなみに
それぞれの例をダウンロードして通常の python を利用して実行することもできますが、そうすると対話的にデータ操作する機会を失なうことになってしまいます:
$ python exercice_1.py
各ステップで対応する図をクリックすることでソースを入手できます。
1.4.2.1. デフォルト設定でプロットする¶
ちなみに
Matplotlib は様々な状態をカスタマイズできるデフォルトの設定を持っています。matplotlib のほとんど全ての状態のデフォルトを制御することができます: 図のサイズや dpi、線幅、色、スタイル、axes、 axis やgrid の状態、テキストやフォントの状態等々。:
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
plt.plot(X, C)
plt.plot(X, S)
plt.show()
1.4.2.2. デフォルトの例示¶
下のスクリプトで、作図の見た目に影響を与える図の設定をあるだけ例示していきます(加えてコメントも)。
ちなみに
以下のスクリプトでは明示的にデフォルトの値を設定していますが、対話的に値を入れてどんな影響があるか調べて遊ぶこともできます (下にある Line properties と `Line styles`_ も参照して下さい)。
import numpy as np
import matplotlib.pyplot as plt
# Create a figure of size 8x6 inches, 80 dots per inch
plt.figure(figsize=(8, 6), dpi=80)
# Create a new subplot from a grid of 1x1
plt.subplot(1, 1, 1)
X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(X), np.sin(X)
# Plot cosine with a blue continuous line of width 1 (pixels)
plt.plot(X, C, color="blue", linewidth=1.0, linestyle="-")
# Plot sine with a green continuous line of width 1 (pixels)
plt.plot(X, S, color="green", linewidth=1.0, linestyle="-")
# Set x limits
plt.xlim(-4.0, 4.0)
# Set x ticks
plt.xticks(np.linspace(-4, 4, 9, endpoint=True))
# Set y limits
plt.ylim(-1.0, 1.0)
# Set y ticks
plt.yticks(np.linspace(-1, 1, 5, endpoint=True))
# Save figure using 72 dots per inch
# plt.savefig("exercice_2.png", dpi=72)
# Show result on screen
plt.show()
1.4.2.3. 色と線の幅を変える¶
ちなみに
最初の一歩として、コサインを青でサインを赤にして両方をより太い線で書いてみましょう。さらに図のサイズをより横長にしてみましょう。:
...
plt.figure(figsize=(10, 6), dpi=80)
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-")
...
1.4.2.4. Setting limits¶
ちなみに
図の現在の範囲は若干窮屈で全てのデータ点をより明確に見られるようにいくらかスペースを与えましょう。
...
plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(C.min() * 1.1, C.max() * 1.1)
...
1.4.2.5. 目盛を設定¶
ちなみに
現在の目盛は理想的とはいえません、なぜならサインとコサインで注目すべき値 (+/-π,+/-π/2) を表示していないからです。これらの値のみを表示するように変更しましょう。
...
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])
plt.yticks([-1, 0, +1])
...
1.4.2.6. 目盛のラベルの設定¶
ちなみに
目盛はきちんと配置されていますが、ラベルが明示的ではありません。3.142 が π であることは想像がつきますが、明示的に書かれた方が好ましいでしょう。目盛の値を設定するときに、対応するラベルをリストとして2番目の引数に与えることができます。latex を利用することでラベルの描画がより素敵になることは覚えておくとよいでしょう。
...
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
[r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
plt.yticks([-1, 0, +1],
[r'$-1$', r'$0$', r'$+1$'])
...
1.4.2.7. spine の移動¶
ちなみに
spine は axis の目盛のマーカーをつなげる線で、データ領域の境界を示します。これらは今まで任意の場所に配置することができます、今までは axis の境界に位置していました。中央に配置してみたいので変更しましょう。(上下左右)の4つがあるので、上と右の色無くして無視し、下と左をデータの空間座標の 0 にします。
...
ax = plt.gca() # gca stands for 'get current axis'
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
...
1.4.2.8. 判例の追加¶
ちなみに
凡例を左上の角に追加します。これは plot コマンドの label キーワード引数(これは凡例を示す箱で利用されます)を追加するだけです。
...
plt.plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")
plt.plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine")
plt.legend(loc='upper left')
...
1.4.2.9. 特定の点に注釈をつける¶
ちなみに
いくつかの注目する点に annotate コマンドを利用して注釈をつけましょう。 2π/3 の値に狙いをつけて、サインとコサインの両方を注釈してみましょう。まず曲線にマーカーとドット付きの直線を描きます。次に annotate コマンドを利用して矢印つきの文章を表示させます。
...
t = 2 * np.pi / 3
plt.plot([t, t], [0, np.cos(t)], color='blue', linewidth=2.5, linestyle="--")
plt.scatter([t, ], [np.cos(t), ], 50, color='blue')
plt.annotate(r'$sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',
xy=(t, np.sin(t)), xycoords='data',
xytext=(+10, +30), textcoords='offset points', fontsize=16,
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
plt.plot([t, t],[0, np.sin(t)], color='red', linewidth=2.5, linestyle="--")
plt.scatter([t, ],[np.sin(t), ], 50, color='red')
plt.annotate(r'$cos(\frac{2\pi}{3})=-\frac{1}{2}$',
xy=(t, np.cos(t)), xycoords='data',
xytext=(-90, -50), textcoords='offset points', fontsize=16,
arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
...
1.4.2.10. 悪魔は細部に宿る¶
ちなみに
目盛りについたラベルが青と赤の線のせいで見にくくなっています。ラベルを大きくし、さらに半透明な白の背景で描画されるようにラベルのプロパティを変更します。これでデータとラベルの両方が見られるようにします。
...
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(16)
label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
...
1.4.3. Figure, Subplot, Axes そして目盛¶
matplotlib で “figure” はユーザーインターフェース内のウィンドウ全体を意味します。この figure の中を “subplots” にすることもできます。
ちなみに
今まで figure と axes の生成を暗黙の内に行なっていました。そういったやり方は手っ取り早く作図するのに便利です。明示的に figure や subplot そして axes を画面上でより制御を加えることもできます。subplot は規則的な格子状に配置されますが、axes は figure 内の自由な位置に配置することができます。どちらも意図に応じて便利に利用できます。figure と subplot を明示的に呼び出さずに動作させてきました。plot を呼び出したとき、matplotlib は gca()
を呼び出して現在の axes を取得し、gca は gcf()
を呼び出し現在の figure を取得します。何もなければ figure()
が呼び出されて figure が作成されて、さらにくわしくにいうと subplot(111)
が作成されます。詳細を見ていきましょう。
1.4.3.1. Figures¶
ちなみに
figure は GUI のウィンドウで “Figure #” をタイトルとして持っています。Figure は 1 から番号づけされます、これは通常 Python では 0 から始まるのと対照的です。これは明らかに MATLAB のやり方からきています。figure の見た目を決めるパラメーターがいくつかあります:
引数 |
デフォルト値 |
説明 |
---|---|---|
num |
1 |
figure の数 |
figsize |
figure.figsize |
figure のサイズ(width, height) 単位はインチ |
dpi |
figure.dpi |
インチ毎のドットの解像度 dots per inch |
facecolor |
figure.facecolor |
描画する背景色 |
edgecolor |
figure.edgecolor |
描画する背景まわりの縁の色 |
frameon |
True |
figure のフレームを描画するかどうか |
ちなみに
デフォルト値はリソースファイルとして保存することができ、ほとんどの場合にそれを使うようにできます。figure の数に関してだけは頻繁に変えるようなことは無いでしょう。
他のオブジェクト同様、figure のプロパティを setp や set_something メソッドによって設定することができます。
GUI で操作するときには右上の角の x をクリックすることで figure を閉じることができます。しかし、close を呼びだすことで figure をプログラム的に閉じることができます。何を引数にするかで、閉じ方は (1) 現在の figure を閉じる(引数無し), (2) 特定の図(figure の番号か figure のインスタンスを引数として与えて), (3) 全ての figure ("all"
を引数に与えて).
plt.close(1) # Closes figure 1
1.4.3.2. Subplots¶
ちなみに
subplot を使うことで、格子状に作図を配置することができます。行の数と列の数と作図の数を引数に与える必要があります。 gridspec コマンドがより強力な代替となることは覚えておくとよいでしょう。
1.4.3.4. Ticks¶
適切に整形された目盛は図を出版品質にするのに重要な役割を果します. matplotlib では目盛を総合的に設定するためのシステムを用意しています. そのシステムとして目盛がどこに現われるか指定する目盛位置指定子, 目盛の見た目を変更する目盛書式指定子があります. 大きい目盛と小さな目盛はお互い独立に位置と書式を指定できます. デフォルトでは小さい目盛は表示されません, つまり小さい目盛の位置指定子は NullLocator
(後述) となっているため, 空リストのみを受けつけます.
1.4.3.4.1. Tick Locators¶
目盛位置指定子は目盛の位置を制御します。位置指定子は以下のようにして設定します:
ax = plt.gca()
ax.xaxis.set_major_locator(eval(locator))
様々な種類の要求に答えるためにいくつかの位置指定子があります:
これらの位置指定子は全て基底クラス matplotlib.ticker.Locator
を継承しています. この基底クラスを継承して自作の位置指定子を作ることもできます. 日付を目盛として扱うのは特に技巧を要します。そのため、matplotlib は matplotlib.dates で特別な位置指定子を提供しています。
1.4.4. 他の種類の作図: 例と例題¶
1.4.4.1. 通常の作図¶
ヒント
You need to use the fill_between command.
下のコードから始めて、領域を埋めていることに注意して右の図を再現してみましょう:
n = 256
X = np.linspace(-np.pi, np.pi, n, endpoint=True)
Y = np.sin(2 * X)
plt.plot(X, Y + 1, color='blue', alpha=1.00)
plt.plot(X, Y - 1, color='blue', alpha=1.00)
図をクリックして解答。
1.4.4.2. 散布図¶
ヒント
色は (X, Y) のなす角に応じて与えています。
下のコードから始めて、マーカーのサイズと色、透明度に注意して右の図を再現してみましょう。
n = 1024
X = np.random.normal(0,1,n)
Y = np.random.normal(0,1,n)
plt.scatter(X,Y)
図をクリックすると解答が得られます。
1.4.4.3. 棒グラフ¶
ヒント
テキストの揃え方 alignment に注意する必要があります。
下のコードから始めて、赤い棒にラベルを追加して右のグラフを再現してみましょう。
n = 12
X = np.arange(n)
Y1 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
Y2 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')
for x, y in zip(X, Y1):
plt.text(x + 0.4, y + 0.05, '%.2f' % y, ha='center', va='bottom')
plt.ylim(-1.25, +1.25)
図をクリックすると解答が得られます。
1.4.4.4. 等高線図¶
ヒント
clabel コマンドを利用する必要があります。
下のコードから始めて、右の図を再現しましょう、colormap に注意して下さい (下にある Colormaps を参照して下さい)。
def f(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 -y ** 2)
n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y)
plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap='jet')
C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)
図をクリックすると解答が得られます。
1.4.4.5. Imshow¶
ヒント
imshow コマンドで画像の origin
に注意し、さらに colorbar を使う必要があります
下のコードから始めて、colormap や画像の補間方法 interpolation、原点 origin に注意して右の図を再現してみましょう。
def f(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
n = 10
x = np.linspace(-3, 3, 4 * n)
y = np.linspace(-3, 3, 3 * n)
X, Y = np.meshgrid(x, y)
plt.imshow(f(X, Y))
図をクリックすると解答が得られます。
1.4.4.6. 円グラフ¶
ヒント
Z を変更する必要があります。
下のコードから始めて、色や切り分けサイズにに注意して、右の図を再現してみましょう。
Z = np.random.uniform(0, 1, 20)
plt.pie(Z)
図をクリックすると解答が得られます。
1.4.4.7. 矢印プロット¶
ヒント
矢印を2回描画する必要があります。
下のコードから始めて、色と方向に注意して右の図を再現してみましょう。
n = 8
X, Y = np.mgrid[0:n, 0:n]
plt.quiver(X, Y)
図をクリックすると解答が得られます。
1.4.4.8. ます目の表示¶
下のコードから始めて、線の種類に注意して右の図を再現してみましょう。
axes = plt.gca()
axes.set_xlim(0, 4)
axes.set_ylim(0, 3)
axes.set_xticklabels([])
axes.set_yticklabels([])
図をクリックすると解答が得られます。
1.4.4.9. 複数の作図¶
ヒント
いくつかの subplot を色々な分割して使うことができます。
下のコードから始めて、右のグラフを再現してみましょう。
plt.subplot(2, 2, 1)
plt.subplot(2, 2, 3)
plt.subplot(2, 2, 4)
図をクリックすると解答が得られます。
1.4.4.10. 極座標¶
ヒント
axes
の行だけ変更する必要があります
下のコードから始めて、右のグラフを再現してみましょう。
plt.axes([0, 0, 1, 1])
N = 20
theta = np.arange(0., 2 * np.pi, 2 * np.pi / N)
radii = 10 * np.random.rand(N)
width = np.pi / 4 * np.random.rand(N)
bars = plt.bar(theta, radii, width=width, bottom=0.0)
for r, bar in zip(radii, bars):
bar.set_facecolor(cm.jet(r / 10.))
bar.set_alpha(0.5)
図をクリックすると解答が得られます。
1.4.4.11. 3D プロット¶
ヒント
contourf を利用する必要があります
下のコードから始めて、右のグラフを再現してみましょう。
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hot')
図をクリックすると解答が得られます。
1.4.5. チュートリアルからさらに¶
Matplotlib は莫大なドキュメントと広大なユーザー、開発者のコミュニティから恩恵を受けています。ここでは注目すべきものへのリンクを示します。
1.4.5.1. Tutorials¶
|
|
1.4.5.2. Matplotlib のドキュメント¶
- User guide
- FAQ
- Installation
- Usage
- How-To
- Troubleshooting
- Environment Variables
- Screenshots
1.4.5.3. コード付属のドキュメント¶
コードにはドキュメントが整理されていて、Python セッションから特定のコマンドに素早くアクセスできます:
>>> import matplotlib.pyplot as plt
>>> help(plt.plot)
Help on function plot in module matplotlib.pyplot:
plot(*args, **kwargs)
Plot lines and/or markers to the
:class:`~matplotlib.axes.Axes`. *args* is a variable length
argument, allowing for multiple *x*, *y* pairs with an
optional format string. For example, each of the following is
legal::
plot(x, y) # plot x and y using default line style and color
plot(x, y, 'bo') # plot x and y using blue circle markers
plot(y) # plot y using x as index array 0..N-1
plot(y, 'r+') # ditto, but with red plusses
If *x* and/or *y* is 2-dimensional, then the corresponding columns
will be plotted.
...
1.4.5.4. ギャラリー¶
matplotlib gallery どうやってそこにあるグラフを描画しているかを調べるのに驚くほど便利です。それぞれの例にはソースがついています。
1.4.5.5. メーリングリスト¶
最後にヘルプを得るために質問できるところで user mailing list があり、より技術的な用途として developers mailing list があります。
1.4.6. クイックリファレンス¶
ここには主要なプロパティやスタイルを見るための表があります。
1.4.6.1. Line properties¶
Property | 説明 |
Appearance |
---|---|---|
alpha (or a) | alpha 透過値 0-1スケール |
|
antialiased | True または False - 描画にアンチエイリアスを使うかどうか |
|
color (or c) | matplotlib の color 引数 |
|
linestyle (or ls) | Line properties を参照 |
|
linewidth (or lw) | 浮動小数点数、線の幅で単位はポイント |
|
solid_capstyle | 実線のふちのスタイル |
|
solid_joinstyle | 実線の連結部分のスタイル |
|
dash_capstyle | 破線のふちのスタイル |
|
dash_joinstyle | 破線の連結部分のスタイル |
|
marker | `Markers`_ を参照 |
|
markeredgewidth (mew) | マーカー記号のまわりの線幅 |
|
markeredgecolor (mec) | マーカーが利用される場合の端の色 |
|
markerfacecolor (mfc) | マーカーが利用される場合の表面の色 |
|
markersize (ms) | マーカーのサイズ、単位はポイント |
1.4.6.2. 線の種類¶
1.4.6.3. マーカー¶
1.4.6.4. カラーマップ¶
全てのカラーマップは _r
を加えることで逆にできます。例えば gray_r
は gray
の逆です。
カラーマップについてより多くの情報を知りたい場合は Documenting the matplotlib colormaps を確認してみて下さい。