Matplotlibで入れ子の図を作成するときのちょっとしたテクニック

Matplotlibで図の中に図が入っているような図(ややこしいなw)を作成するときにいくつかはまったのでメモしておく.

図が規則的に並んでいるときはsubplotを使えば良いが, 特定の場所に表示したいときはaxesを利用する. 普通一つの図しか作らない場合はmatplotlib.pylab.plot等とするし, 複数つくる場合でもmatplotlib.pylab.subplotなどとしてできる.

しかし, 実際には一度figureを作成してから処理する必要のある場合がある. このfigureが曲者で, figureのメンバ変数はmatplotlib.pylabに対して呼んでいた関数と微妙に名前も引数も違う. 具体的には,

import matplotlib.pylab as plt
plt.subplot(111)
plt.axes((0.1, 0.1, 0.5, 0.5))
plt.legend(loc='best')
plt.xticks((0, 1, 2), ('zero', 'one', 'two'))

とできるところ, figureの場合,

import matplotlib.pylab as plt
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = fig.add_axes((0.1, 0.1, 0.5, 0.5))
h, l = ax1.get_legend_handles_labels()
fig.legend(h, l, 'best')
# ax2.legend()
ax2.set_xticks((0, 1, 2))
ax2.set_xticklabels(('zero', 'one', 'two'))

というふうな感じ. matplotlib.pylabでsubplotなどしている場合と比べてaxesを明確に扱った方が自分がどこに描画しているのかがわかりやすく, 制御できるため良いのだが, いかんせん混乱させられる.

http://d.hatena.ne.jp/bettamodoki/20111208/1323317469

以下に簡単な入れ子の図を作成してレジェンドをまとめたものをメモしておく.

import numpy
import matplotlib.pylab as plt

fig = plt.figure() # Figureの作成
ax1 = fig.add_subplot(111) # 通常の描画領域(全体)を指定するaxes
ax2 = fig.add_axes([0.2, 0.2, 0.3, 0.3]) # 左下の小窓を指定するaxes

x = numpy.linspace(0, 1, 100) # , 101)とすると0.5が入ってtanがふっとびます
ax1.plot(x, numpy.sin(x * numpy.pi * 2), 'r-', label='Sin')
ax1.plot(x, numpy.cos(x * numpy.pi * 2), 'g-', label='Cos')
ax2.plot(x, numpy.tan(x * numpy.pi), 'b-', label='Tan')

h1, l1 = ax1.get_legend_handles_labels() # ax1のartist(Line2D)とlabelの取得
h2, l2 = ax2.get_legend_handles_labels() # ax2のartistとlabelの取得
ax1.legend(h1 + h2, l1 + l2, 'upper right') # ax1のレジェンドとしてまとめて表示
fig.show()

ax1.legendをfig.legendとしても良いが位置指定が異なるので注意. また, ax1.legendでloc='best'としてもどうやらax2のことは無視してbestな場所を選ぶので, ax2で隠れてしまう可能性がある.

変なエラーが出たらコメント内の日本語のせいかもしれないので消してください.

http://matplotlib.sourceforge.net/users/artists.html
http://matplotlib.sourceforge.net/users/legend_guide.html
http://matplotlib.sourceforge.net/api/figure_api.html