0
0

Jupyter + Matplotlib

Last updated at Posted at 2024-06-26

よく知らなくても何となく使えてしまう matplotlib。しかしちょっと凝ったことしようとするとめちゃ難しい。。。という事で調べてみました。

目標: Pandas で描いたグラフに線を重ねてみたり色々工夫したい。

参考: https://matplotlib.org/stable/users/explain/quick_start.html

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

Pandas では、とても簡単にグラフを描く事ができます。例えば Series オブジェクトの plot() を呼ぶだけでグラフになります!

ax = pd.Series(np.sin(np.linspace(0, 2 * np.pi, 100))).plot()
<Axes: >

output_3_1.png

簡単で良いが、実は plot() は内部的に Matplotlib というライブラリで実装されていて、これ以上の凝ったことをしようとすると Matplotlib の知識が必要になります。そこで色々な疑問がでてきました。。。

  • この plot() の戻り値の <Axes: > って何なのだろう?? 👉 axes とは、axis(軸) の複数形でアクシーズと読むらしい
    • ちなみに、最後の行で plot() した時の出力に <Axes: > のように戻り値が表示されてしまうのは、行末に ; を付加すると抑制できます。マメ知識です。
  • 何で勝手に表示されるのだろう? plot() で表示しないで、後で表示する事は可能なのかな??

これらの疑問に答えるために、まず Matplotlib の二つのコーディングスタイルについて確認します。

明示スタイル (オブジェクト指向スタイル)

こちらがお薦めらしい。明示スタイルとは、plt.subplots() で明示的に Figure や Axes オブジェクトを作成し、Axes を明示的に操作して描画するスタイルです。Pandas の plot()Axes オブジェクトを返すのでこのスタイルが使えそう。

x = np.linspace(0, 2 * np.pi, 100)  # x 軸の作成

fig, ax = plt.subplots(figsize=(8, 2)) # 明示的に Figure と Axes を作る。
ax.plot(x, np.sin(x)) # 作成した Axes に sin カーブを描画
ax.plot(x, np.cos(x)); # 作成した Axes の cos カーブを描画

output_5_1.png

暗黙スタイル (pyplot スタイル)

伝統的なスタイルらしい。暗黙のスタイルとは plt.figure で 暗黙のうちに Axes を有効化して、plot に対して描画メソッドを呼ぶ事で有効化された暗黙の Axes に描画するスタイルです。明示スタイルの plt.subplots() で作成した最後の Axes も暗黙に有効化されるので、どうしてもやりたければ明示と暗黙を両方使う事も可能。

plt.figure(figsize=(8, 2)) # 新しい Figure を有効化する。 
plt.plot(x, np.sin(x)) # 暗黙の Axes に sin カーブを描画
plt.plot(x, np.cos(x)); # 暗黙の Axes の cos カーブを描画

output_7_1.png

色々なスタイルを混ぜて描画

試しに、Pandas スタイル、明示スタイル、暗黙スタイルを混ぜてみても一応動く。

ax = pd.Series(np.sin(np.linspace(0, 2 * np.pi, 100))).plot() # Pandas で描画
ax.plot(x, np.sin(x)) # Pandas で作成した Axes に sin カーブを描画
plt.plot(x, np.cos(x)); # 暗黙の Axes も有効になっているので、そこにさらに cos カーブを描画

output_9_1.png

今度は逆に、Matplotlib で作成した Axes に Pandas で描画する。

fig, ax = plt.subplots(figsize=(8, 2)) # 明示的に Figure と Axes を作る。
ax.plot(x, np.sin(x)) # 作成した Axes に sin カーブを描画
plt.plot(x, np.cos(x)) # 暗黙の Axes も有効になっているので、そこにさらに cos カーブを描画
pd.Series(np.sin(np.linspace(0, 2 * np.pi, 100))).plot(); # Pandas で描画

output_11_1.png

色々なレイアウトで描画

Pandas の plot() には ax= で描画したい Axes を指定できるので、明示スタイルを使うと複数の Axes に色々なレイアウトでグラフを描画できます。

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(8, 2)) # 明示的に Figure と横に並んだ二つの Axes を作る。

pd.Series(np.sin(np.linspace(0, 2 * np.pi, 100))).plot(ax=ax1) # Pandas で ax1 に描画
pd.Series(np.cos(np.linspace(0, 2 * np.pi, 100))).plot(ax=ax2) # Pandas で ax2 に描画

ax1.text(20, 0, "ax1: left")
plt.text(20, 0, "ax2: right"); # 暗黙の Axes に描画すると、後で生成された Axes (ax2) に描画される。

output_13_1.png

Jupyter で勝手に描画しないようにインタラクティブモードを OFF にする

Jupyter Notebook 上で Matplotlib を使うと、特に何もしてないのにグラフが表示されてしまいます。これはインタラクティブモードが ON になっているからだそうです。

この動作を抑制するには plt.ioff() を使います。

参考: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.ioff.html

plt.ioff()
fig, ax = plt.subplots(figsize=(8, 2))
pd.Series(np.sin(np.linspace(0, 2 * np.pi, 100))).plot(ax=ax)

インタラクティブモードを OFF にすると、最初のセルで描画したグラフを表示せず、後のセルで表示する事ができます。

pd.Series(np.cos(np.linspace(0, 2 * np.pi, 100))).plot(ax=ax)
plt.show()

output_17_0.png

Matplotlib を使う関数のお作法

Matplotlib に描画する関数を描く時は、最初の引数を Axes にして最後を param_dict にするのがお作法なようです。お作法に従うと色や形を変えたり変更が容易になります。例えばこのサインカーブの描画を関数 plot_sin() にします。

plt.ion()
def plot_sin(ax, offset, param_dict = {}):
    x = np.linspace(0, 2 * np.pi, 100)  # x 軸の作成
    ax.plot(x, np.sin(x + offset), **param_dict) # 暗黙の Axes に sin カーブを描画

fig, ax = plt.subplots(figsize=(8, 2))
plot_sin(ax, 0)

output_20_0.png

plot_sin()param_dict を与える事で色々なサインカーブを描きます。

fig, ax = plt.subplots(figsize=(8, 2))
plot_sin(ax, 0)
plot_sin(ax, 1, {"color": "blue", "linewidth": 3, "linestyle": '--'})
plot_sin(ax, 2, {"color": "orange", "linewidth": 2, "linestyle": ':'})
plot_sin(ax, 3, {'marker': '+'})

output_22_0.png

色の選択 (TODO)

ひとつの Axes に複数のグラフを描くと、別の色で描画されます。これがどのような仕組みになっているのか調べました。グラフに表示する色は plt.rcParams['axes.prop_cycle'].by_key()['color'] で定義されている。

参考: https://matplotlib.org/stable/api/matplotlib_configuration_api.html#matplotlib.rcParams

colors = plt.rcParams['axes.prop_cycle'].by_key()['color']

試しにこの色を左から右に描画してみます。

fig, ax = plt.subplots(figsize=(8, 2))
for i, color in enumerate(colors):
    ax.plot([i, i], [0, 1], linewidth=20, color=color)

output_25_0.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0