Matplotlibはじめました

最近、『Pythonデータサイエンスハンドブック ―Jupyter、NumPy、pandas、Matplotlib、scikit-learnを使ったデータ分析、機械学習』と『最短コースでわかる Pythonプログラミングとデータ分析』を読んでいる。

特にかれるのが Matマットplotプロットlibリブ というグラフ描画ライブラリで、巧く使えばかなり複雑なデータもそこそこの品質で可視化できることには驚いた。

実際に手を動かしてりをしてみたので、備忘録として以下にまとめてみる。

基本の正弦波

まずは {\sin (x)} をデフォルト設定のままプロットする。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.show()


線の色

次に、線の色を変えてみる。 16進数指定のほか、HTMLで用いられる色名を直接指定することもできる。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x), color='#007f00')  # 色を指定
plt.show()


軸の範囲

さらに、軸の範囲を明示的に指定することもできる。もともと {x} の範囲は {0 \leq x \leq 10} であったのを、{0 \leq x \leq 2\pi} の範囲に設定して描画する。

{x} 軸の目盛りの最大値が 6.3弱 ({=2\pi}) になっているところに注目。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x))
plt.xlim(0, 2 * np.pi)  # x軸の範囲を 0 ≦ x ≦ 2π に設定
plt.show()


軸の縮尺

ここまでの例では、{x}軸と{y}軸のアスペクト比が 1:1 ではなく、使途によってはあまり具合のよいものとはいえない場合がある。

そこで、2軸の縮尺を揃えてみよう。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x))
plt.axis('equal')  # x軸とy軸の縮尺を一致させる
plt.xlim(0, 2 * np.pi)
plt.show()


軸の間隔

{x}軸の目盛りの間隔が、1きざみになってしまっている。 本来は、{\displaystyle\frac{\pi}{4}}ずつ目盛りを刻みたいとしよう。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

ax = plt.axes()

ax.plot(x, np.sin(x))
ax.axis('equal')

ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4))

ax.set_xlim(0, 2 * np.pi)
plt.show()


目盛のカスタマイズ

目盛りの刻み幅は {\displaystyle\frac{\pi}{4}} となったが、肝心のラベルが小数表示になってしまっており、いまひとつ格好が良くない。

本来は {n \pi}のように、{\pi}の何倍の地点にあるかを一目で判るようにするため、目盛りの表示をカスタマイズしてみる。

import matplotlib.pyplot as plt
import numpy as np

def format_func(value, tick_number):
  N = int(np.round(2 * value / np.pi))
  if N == 0:
    return '0'
  elif N == 1:
    return r'$\pi/2$'
  elif N == 2:
    return r'$\pi$'
  elif N % 2 > 0:
    return r'${0}\pi/2$'.format(N)
  else:
    return r'${0}\pi$'.format(N // 2)

x = np.linspace(0, 10, 100)

ax = plt.axes()

ax.plot(x, np.sin(x))
ax.axis('equal')

ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4))

ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))

ax.set_xlim(0, 2 * np.pi)
plt.show()


注釈

最後に、グラフの中に注釈を追加してみる。

LaTeX でレポートや論文を書く場合は、overpic.sty などで図版の上から文字を重ね打ちする技法も使えるが、簡単な注釈ならば Matplotlib で入れることもできる。

import matplotlib.pyplot as plt
import japanize_matplotlib  # 日本語を有効化する
import numpy as np

def format_func(value, tick_number):
  N = int(np.round(2 * value / np.pi))
  if N == 0:
    return '0'
  elif N == 1:
    return r'$\pi/2$'
  elif N == 2:
    return r'$\pi$'
  elif N % 2 > 0:
    return r'${0}\pi/2$'.format(N)
  else:
    return r'${0}\pi$'.format(N // 2)

x = np.linspace(0, 10, 100)

ax = plt.axes()

ax.plot(x, np.sin(x))
ax.axis('equal')

ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 4))

ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))

# 注釈を追加
ax.annotate('極小', xy = (3 * np.pi / 2, -1), xytext = (3.5, -1.5),
            arrowprops = dict(arrowstyle = '->',
                              connectionstyle = 'angle3,angleA=0,angleB=-90'))

ax.set_xlim(0, 2 * np.pi)
plt.show()