matplotlibで等高線やら何やらのプロット

今回は等高線や、疑似カラープロット(?)に挑戦です。
今までと違い、x, yのデータの他にz方向のデータを持っています。


以前のお話はこちら
matplotlibでグラフを書く - たこ焼き食べた.net

疑似カラープロット(?)

行列の作り方

これは以下の等高線などでも使う知識なので重要です。
今回挑戦するx, y, zの3軸の情報を持つグラフは、今までと若干行列の与え方が異なります。
例えば、5*5の行列をプロットするとすると以下の行列が必要となります。

このように、x, y, zがそれぞれ、5*5の情報を持つ必要があります。
通常、x, y, zは

x = arange(5)
y = arange(5)
Z = array([[24, 32, 12, 16, 21],
           [23, 24, 25, 26, 27],
           [43, 36, 32, 26, 25],
           [30, 32, 25, 21, 20],
           [20, 32, 23, 20, 14]])

のように、x, yは1次元の配列かと思います。
従ってこれを2次元の配列に変換してあげる必要があります。
これには、meshgrid関数を用います。

X, Y = meshgrid(x, y)

このようにすると、X, Yに、x, yを2次元に変換した配列が代入されます。
このように、3次元の情報を持つグラフでは、
X, Yと、上に示したZのような2次元配列を利用してプロットしていきます。

pcolor関数

pcolor関数を使うことで、疑似カラープロットを描画することができます。
pcolor関数は以下のような動作をします。

このように、ある点をプロットする時は、その要素とその次の要素で囲まれた領域を塗り潰します。
というわけで、例えば、5*5の行列をプロットしたいときは、x, yは6個の要素を持っている必要があります。
間違いやすいので注意してください。
(というか前節の図も間違って4*4のグラフになってしまっていますね。。。)


例えば、以下のようにプロットすることができます。

from pylab import *

N = 5
x = arange(N+1)
y = arange(N+1)
Z = array([[24, 32, 12, 16, 21],
           [23, 24, 25, 26, 27],
           [43, 36, 32, 26, 25],
           [30, 32, 25, 21, 20],
           [20, 32, 23, 20, 14]])

X, Y = meshgrid(x, y)
pcolor(X, Y, Z)
colorbar

show()


ちなみに、colorbar関数を付けることで、カラーバーを表示することができます。
値と色の関係を示しますのでほぼ必須かと思います。

サンプル

もうちょっと複雑な図を以下に載せてみます。
上のやつは四角がはっきりしていて地味ですし。。。

from pylab import *

x = arange(0, 10.1, 0.1)
y = arange(0, 10.1, 0.1)

X, Y = meshgrid(x, y) 
Z = cos(X) + cos(Y)

pcolor(X, Y, Z)
colorbar()

show()

上述のような理由で、x=10, y=10のときのZがプロットされていないが、今回は無視。。。
というわけで以下のようなグラフができました。

色合いを変える。

色合いの設定を変えることができます。
以下のような関数を使えば簡単だと思います。

  • autumn
  • bone
  • cool
  • copper
  • flag
  • gray
  • hot
  • hsv
  • jet
  • pink
  • prism
  • spring
  • summer
  • winter
  • spectral

結構たくさんありますね。
以下に、pinkの例を示します。

from pylab import *

x = arange(0, 10.1, 0.1)
y = arange(0, 10.1, 0.1)

X, Y = meshgrid(x, y) 
Z = cos(X) + cos(Y)

pcolor(X, Y, Z)
colorbar()
pink()

show()

等高線

疑似カラープロットの話を理解していれば簡単です。
contour関数を用いて、

contour(X, Y, Z)

でプロットできます。
なお、等高線の数は以下のように引数を与えてあげることで指定できます。

contour(X, Y, Z, V)

この場合、等高線の数はV個になります。


というわけでサンプル。
カラーマップは先程と同様に指定できます。

from pylab import *

x = arange(0, 10.1, 0.1)
y = arange(0, 10.1, 0.1)

X, Y = meshgrid(x, y) 
Z = cos(X) + cos(Y)

contour(X, Y, Z)
colorbar()
spring()

show()

grayバージョン

matplotlibのグラフの体裁を整える

前回は折れ線グラフを作成しました。
ただ、グラフにはx軸の名前だったり凡例だったりが必要ですよね。
今回はそういった内容をやります。
また、複数段にわたってプロットする方法を記します。


以前のお話はこちら
matplotlibでグラフを書く - たこ焼き食べた.net


今回もほとんどの内容を公式サイトを参考に記しています。
Matplotlib: Python plotting — Matplotlib 3.0.3 documentation

テキスト関連

グラフの軸だったりに表示するテキストの設定を行ないます。
今回は簡単に、軸とタイトル、凡例などのみです。
なお、matplotlibでは日本語の文字列を埋め込むことができませんのでご注意ください。


テキストを図中に埋め込んだり、矢印を描画する手法もありますが、今回は省略します。
というより使ったことがないので。。。
表なんかも埋め込めるんですね。
Pyplot tutorialにあるので、気になる方はどうぞ。
Pyplot tutorial — Matplotlib 2.0.2 documentation


さて、今回のサンプルは下図のようになります。

from pylab import *

x = arange(0, 5, 0.1)
y = cos(x)

plot(x, y)
legend(('legend dayo',)) # 凡例
# どうでもいいけど、要素数一つのタプルは(A,)のようにカンマが必要です。お忘れなく。。。(忘れてた)
xlabel("Time [ps]", fontsize=20, fontname='serif') # x軸のタイトル
ylabel(r"$\mu_0$", fontsize=20, fontname='serif') # y軸
title("test", fontsize=25, fontname='serif') # タイトル
xticks(range(5), ("test", "1", "2", "3", "#4")) # xの目盛
yticks(fontsize=15) # yの目盛

show()


フォントの設定

以下のテキストは、フォントの指定の仕方等が一緒です。
フォントでいじるのはフォント名とフォントサイズがメインだと思います。
これらは、テキストを表示する関数に、キーワード引数として

  • fontname
  • fontsize

を与えてあげれば良いかと思います。
例えば、xlabel(後述)関数なら、

xlabel("test", fontname='serif', fontsize=20)

などとなります。

x, y軸のラベル, グラフのタイトル

関数xlabelとylabelによって指定することができます。
グラフのタイトルはtitle関数です。

軸のテキストの設定

軸についてる目盛の文字の大きさや、目盛の文字列も指定できます。
これは、xticks, yticks関数を使います。
フォントのサイズのみだけでも指定できます。


軸の文字列の変更は以下のようになります。

xticks([1,2,3,4,5], ('#1', '#2', '#3', '#4', '#5')

1番目はx軸の元の数字列、 2番目が変更後の文字列です。
1番目と2番目の要素のそれぞれが対応します。

凡例

凡例はlegend()関数で表示できます。
凡例内の文字列は、以下のようにタプルで与えることで指定できます。
plotする順番が早い順に、タプルの要素が割り振られます。

legend(('legend 1', '2', '3'), loc='upper left')

loc引数で、位置を指定することができます。
指定しない場合は最善の位置を、プログラム側が探してくれるので、指定する必要はほとんどないと思います。

数式の入力

Texの形式で数式を与えることで、数式を出力することもできます。
これはTexを入れてなくても出力することができ、大変便利です。
Tex同様、$$で囲んであげます。

xlabel(r'$\mu_0$')

ここで、Texの形式だと\muのように\マークが出現します。
Python的にはこれはエスケープシーケンスなので出力できません。
というわけで、文字列の前にrをつけてあげます。(詳細はraw stringで調べてみてください)
これによって、Texと同じ形式で出力することができます。


Texの数式の使い方は他のページを参考にしてください。
次に示すページはまとまっていてわかりやすいかと思います。
LaTeXコマンドシート一覧

複数段のプロット

複数段に分けてプロットする方法を示します。
その前に簡単なmatplotlibの仕組みも説明します。

Figure, Axes

matplotlibでは、図全体をFigureと呼びます。
そして、その中にあるグラフ(複数個でも構わない)をAxes(複数形で、単数形だとAxis)と呼びます。
直訳すればFigureは図、Axesは軸ですね。
複数のグラフを作成する時は、FigureにAxesを追加していきます。

Current Figure, Current Axes

matplotlibにはCurrent Figure, Current Axesという考え方があります。
現在操作している図(Current Figure, Current Axes)を、プログラム側で保存しています。
適当にplotやxlabelなどの関数を使うと、これらの現在操作している図の内容を変更します。
複数グラフがある時なども、現在操作しているグラフを変更することでそれぞれを操作することができます。
現在操作している軸、図はそれぞれ、gca(), gcf()関数で取得することができます。
そんなに使うこともないかもしれませんが、凝った図を書く時には必要になるかもしれません。

複数段プロットの仕方

図はfigure()で関数で作成することができます。
一つの図だけで良い場合は、省略可能です。
今迄の折れ線グラフでも実は省略しています。書いてもよいです。
Axes(軸)も今までは一つしかなかったので、省略してきました。


しかし、今回はグラフをいくつもつくりたいので、Axesを自分で定義する必要があります。
このための関数がいくつか用意されているようですが、subplot関数が便利です。
subplot関数は、図(figure)を等間隔に分割して、そこにグラフを流し込みます。
同じ大きさのグラフを複数並べたいときには便利です。


subplot関数は

subplot(3桁の数字)

を取ります。3桁の数字は、

  • 100の位は、行の数
  • 10の位は、列の数
  • 1の位は何番目の軸を作成するか

を示します。例えば

subplot(211)

は「2*1のグラフの1つ目のグラフ」を作成します。
どうやらこれがCurrent Axesになります。


例えば、2*1のグラフを作成することにします。
上の行にはsinを、下の行にはcosを表示します。

from pylab import *
x = arange(1, 10, 0.1)
y1 = sin(x)
y2 = cos(x)

# 上の行のグラフ
subplot(211)
plot(x, y1)
xlabel("1") # 上の行のxlabel

# 下の行のグラフ
subplot(212)
plot(x, y2)
xlabel("2") # 下の行のylabel

show()


ここで、subplotを実行するとCurrent Axesが変わるという点に注意してください。
subplotを定義して、次のsubplotまでの間にグラフの設定(xlabelやらxticksやら)を書けば、
その部分のグラフの設定を変更することができます。

グラフのクリア

matplotlibはグラフをfigure(図)に重ねて描いていきます。
消したいときはclf()としましょう

グラフの範囲

グラフのx, y軸それぞれの表示範囲を指定することができます。
あくまで表示範囲です。
これにはxlim(), ylim()を使います。
>python|
xlim(0, 3)
|

とすれば、0から3までの範囲を表示します。
片方だけ指定する時は

xlim(xmin=0)
xlim(xmax=3)

などと別に書きます。


また、axis関数を使って指定することもできます。

axis([xmin, xmax, ymin, ymax])

のようにも指定できますが、それよりも文字で指定する方法が重宝します。

axis('scaled')

とすると、x, y軸のスケールが同じになります。
またx, yのある範囲のみを表示するときは'tight'です。
他にもありますので、気になる方は公式ドキュメントを参照してみてください。

スケールの指定(片対数等)

xscale, yscale関数に'log'を引数で与えてあげると、その軸が対数になります。

xscale('log')

matplotlibで棒グラフを書く

今回は棒グラフを書きます。
フーリエ変換だとかもあるみたいですが、私がよく理解していないので。。。
他のグラフも、ギャラリーをに載ってるソースコードを読めば理解できるかと思います。
いろいろサンプルがあって非常に便利ですね。


以前のお話はこちら
matplotlibでグラフを書く - たこ焼き食べた.net

棒グラフ

棒グラフにはbar関数を使います。これは縦方向の棒グラフです。
横方向にはbarh関数を使います。

縦の棒グラフ

bar関数の引数は、

bar(棒の左端のx座標(left), 棒の高さ(bottom))

が最低限の条件となります。
更にいろいろと条件を指定することができ、色や線幅などの他にも、
棒の幅を指定するwidth, 一番下のy座標を決めるbottomなどがあります。
棒は、四角形で描画されますが、この四角形は以下の2点を結ぶ直線を対角線に取ります。

(left, bottom), (left + width, bottom + height)

詳細は公式を参考にしてください。
pyplot — Matplotlib 2.0.2 documentation


さて、ではサンプルです。

from pylab import *

x = arange(5)
y = (32, 24, 41, 2, 16)
width = 0.5

barh(x, y, width, color='r', edgecolor='k')

ylabel('nannka', fontname='serif')
xticks(x + width/2, ('#1', '#2', '#3', '#4', '#5'))
legend(("bar dayo",))

show()


x軸の目盛を指定するxticksは、公式のサンプルを参考にしました。
これは、棒の中央にラベルが来るように工夫しています。

横の棒グラフ

横方向に寝かした棒グラフです。
barh関数を使っています。
ここでは、一番下の値を変更しています(left引数)
これは、bar関数ではbottom引数に対応しています。

from pylab import *

x = arange(5)
y = (32, 24, 41, 2, 16)
left = (-20, -12, -24, -32, -13)
width = 0.5

barh(x, y, width, left=left, color='r', edgecolor='k')

xlabel('nannka', fontname='serif')
yticks(x + width/2, ('#1', '#2', '#3', '#4', '#5'))
legend(("bar dayo",))

show()