プロット

matplotlib

プロット(グラフ描画)には matplotlib(マットプロットリブ)という MATLAB ライクなライブラリを使います。

もし,例えば

import matplotlib.pyplot as plt

plt.plot([-1,1])
plt.show()

でエラーになるなら,~/.matplotlib/matplotlibrcバックエンドの指定を見直します。Macの場合は

backend: MacOSX

または pip install PyQt5 して

backend: Qt5Agg

とします(うまくいかなければ MacOSX Qt5Agg Qt4Agg Gtk3Agg GTK3Cairo TkAgg WxAgg Agg Cairo の中から選んでください)。

デフォルトのフォントでは日本語が出ません。日本語を出したいなら,システムにインストールされている適当な TrueType または OpenType フォント名を ~/.matplotlib/matplotlibrc に書き加えます。Macなら例えば

font.family: AppleGothic

でよさそうです。あるいは,こちらから IPAex ゴシックをいただいてきてシステムにインストールし,次のように書き加えます:

font.family: IPAexGothic

新しいフォントをインストールしたら,フォント名のキャッシュ ~/.matplotlib/font* は消します(次回 matplotlib 使用の際に自動生成されます)。

matplotlib 3.1.0 以降は TrueType Collection も表示できるようになりましたので,Windows なら

font.family: MS Gothic

でもかまいません。ただ,TrueType Collection では PDF への保存ができないようです。

なお,font.family のデフォルト値は sans-serif で,DejaVu Sans が使われます。serif と指定すれば DejaVu Serif になります。DejaVu は Bitstream Vera ベースの良質なフォントです。

PDF で保存する場合,TrueType フォントは Type 3 形式でサブセット埋め込みされます。OpenType の Source Han Sans などは,日本語表示には使えますが,サブセット化できず,丸ごと埋め込まれてしまい,PDF のファイルサイズが巨大になります。また,今のところ,TrueType Collection は PDF 保存に対応していないようです。

~/.matplotlib/matplotlibrc を作る前の,システムの matplotlibrc の位置は,ターミナルに次のコマンドを打ち込めば表示されます:

python3 -c "import matplotlib; print(matplotlib.matplotlib_fname())"

簡単なプロットで試してみましょう。ターミナルで IPython を使うなら ipython --matplotlib として起動します(--matplotlib はデフォルトでオンになっている環境もあります)。Jupyter Notebook の環境なら

%matplotlib inline

という1行をまず打ち込みます。そして,次のように打ち込みます:

import matplotlib.pyplot as plt

plt.plot([-1,1])
plt.title('日本語タイトル')

これでもしグラフが出ないなら plt.show() と打ち込みます。日本語タイトルも軸のマイナスも化けずに出れば合格です。もし日本語が出てもマイナスが化ける場合は,フォントに MINUS SIGN (U+2212) がないのでしょう。マイナスを HYPHEN-MINUS (U+002D) で代用するために ~/.matplotlib/matplotlibrc に次の1行を追加します:

axes.unicode_minus: False

環境によっては,plt.show() でグラフが出ても,グラフの窓を閉じない限り,次に進めなくなります。この状態を「ブロック」といいます。ブロックしないようにするには plt.show(block=False) のようにオプションを付けます。対話型環境でないスクリプト中でこれをすると,グラフがすぐ消えてしまいます。

現在のプロットの中身をクリアするのは plt.clf(),最後に描いたプロットを消すのは plt.close() です。全部のプロットを消すには plt.close("all") とします。

IPython では,詳しいヘルプは例えば ?plt.plot のように打ち込めば現れます。

プロットのスタイルはいろいろ選べます。例えば

plt.style.use('ggplot')

とすれば R の ggplot のスタイルになります。スタイルは plt.style.available で一覧できます。もっと細かい設定は plt.rcParams と打ち込めば一覧できます。フォントも

plt.rcParams['font.family'] = 'IPAexGothic'
plt.rcParams['font.size'] = 12

あるいは同じことですが

plt.rc('font', 'family'='IPAexGothic', 'size'=12)

のようにして変更できます。デフォルト状態に戻すには plt.rcdefaults() と打ちます。

タイトルやラベルに日本語のフォントを使う程度なら,特にデフォルトのフォントを変えなくても,次のように関数にオプションで与えることもできます:

plt.title('日本語タイトル', fontfamily='IPAexGothic', fontsize=20)
plt.xlabel('日本語のx軸タイトル', fontfamily='IPAexGothic')

より簡単な方法として japanize-matplotlib をインストールして import japanize_matplotlib する方法があります(pip install して import するだけで matplotlib を日本語表示対応させる参照)。Google Colaboratory などリモートの環境で日本語を表示するときに便利です。

!pip install japanize-matplotlib

import matplotlib.pyplot as plt
import japanize_matplotlib
plt.plot([1,2])
plt.title('日本語タイトル')

ファイルへの保存

ファイルへの保存は,メニューからも,プログラムでもできます。アクティブなプロット(最後に描いたプロット)を保存しますので,例えば「Figure 2」を保存したいなら,あらかじめ plt.figure(2) と打ち込んでアクティブにしておきます:

plt.savefig('filename.png', bbox_inches="tight")  # デフォルト: dpi=100
plt.savefig('filename.pdf', bbox_inches="tight")
plt.savefig('filename.pgf', bbox_inches="tight")

最後のPGF(Portable Graphics Format)はTeXのTikZのベースとなるグラフィック言語です。これは次のような形のLaTeXファイルを xelatexlualatex でコンパイルすることによってPDFに変換できます:

\documentclass{standalone}
\usepackage{pgf}
\usepackage{fontspec}
\begin{document}
\input{filename.pgf}
\end{document}

PDFの場合は,次のようにすることもできます:

from matplotlib.backends.backend_pdf import PdfPages

with PdfPages('foo.pdf') as pdf:
    # ここで図を描く
    pdf.savefig(fig)

文字だけLaTeXを使う

軸の文字やタイトル・キャプションなどの数式は,LaTeX風に $ で囲んで書けば,ちゃんと解釈してくれます。その際に,文字列は r'...' のように r を付けて書けば,\ を特別扱いしない「生の」(raw)文字列として扱われます。

latexdvipngdvipsgs コマンドが使える環境では,次のように text.usetexTrue にすれば,本当に文字部分だけLaTeXを起動して,きれいな出力を得ることができます。

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['text.usetex'] = True

x = np.linspace(-5,5,101)
y = 1 / (1 + np.exp(-x))
plt.figure(figsize=(5, 3))
plt.plot(x, y, 'k')
plt.xlabel(r'$x$')
plt.ylabel(r'$y$')
plt.title("Sigmoid Function")
plt.legend([r'$y = \frac{1}{1+e^{-x}}$'])
plt.savefig("sigmoid.pdf", bbox_inches="tight")

デフォルトではComputer Modernフォント(数式はcmrやcmmi,タイトルはcmss)になります(PDFにはフォントがType 1形式で埋め込まれます)が,次のようにしてフォントを指定できます:

plt.rcParams['font.family'] = 'serif' # あるいは 'sans-serif' など
plt.rcParams['font.serif'] = 'times'  # あるいは 'palatino' など
plt.rcParams['font.sans-serif'] = 'helvetica'

Timesでは \usepackage{mathptmx},Palatinoでは \usepackage{mathpazo},Helveticaでは \usepackage{helvet} がプリアンブルに書き込まれます。実際に処理されるLaTeXファイルは例えば次のようになります:

\documentclass{article}
\usepackage{type1cm}
\usepackage{mathpazo} % Palatino指定で入る
\usepackage{helvet}   % Helvetica指定で入る
\usepackage{textcomp}
\usepackage[utf8]{inputenc}
% ここに別途指定したプリアンブルが入る
\usepackage[papersize={72in,72in},body={70in,70in},margin={1in,1in}]{geometry}
\pagestyle{empty}
\begin{document}
\fontsize{10.000000}{12.500000}{\rmfamily $y = \frac{1}{1+e^{-x}}$}
\end{document}

次のようにしてプリアンブルを直接指定することもできます:

plt.rcParams['text.latex.preamble'] = r'\usepackage{tgtermes},\usepackage{newtxmath}'

プリアンブルを指定する場合は,他のコードと衝突してエラーにならないように,十分注意が必要です。上の例では,\usepackage{newtxtext} を指定するとエラーになったので,\usepackage{tgtermes} にしました。

~/.matplotlib/tex.cache にLaTeXファイルやdviファイルがたくさんできます。消してもかまいませんが,同じ文字列が出てきたら再利用されますので,特に消す必要はありません。

その他

図の大きさを指定する:

plt.figure(figsize=[6.4, 4.8])  # デフォルトは6.4×4.8インチ

あるいはデフォルトを変更する:

plt.rcParams['figure.figsize'] = (6.4, 4.8)

(Jupyter Notebook などの場合)図を PNG でなく SVG にする(拡大しても荒くならない):

from IPython import display
display.set_matplotlib_formats('svg')

軸の最小値・最大値を指定する:

plt.xlim(最小値,最大値)
plt.ylim(最小値,最大値)

軸の目盛位置と目盛ラベルを指定する:

plt.xticks([-np.pi,0,np.pi], [r'$-\pi$','$0$',r'$\pi$'])

対数目盛:

plt.xscale('log')
plt.yscale('log')

グリッド描画:

plt.grid()

どちらかの軸の範囲を拡大して両軸の目盛を等しくする:

plt.axis('equal')

プロット領域の縦横比を調節して両軸の目盛を等しくする:

plt.axis('scaled')

水平線,垂直線を引く:

plt.axhline()  # 引数を省略すればy=0の水平線
plt.axvline()  # 引数を省略すればx=0の水平線
plt.axhline(0.5, linewidth=1, color="black")

プロットをクリア:

plt.clf()

全プロットを閉じる:

plt.close("all")

参考


Last modified: