組み込み開発のためのPython · レッスン 130 / 238
Matplotlib Pyplot:pyplotを使う
pyplotは現在のFigureやAxesを操作する状態ベースのインターフェースです。短い試行に便利ですが、複数の図を作る場合はオブジェクト指向形式との違いを理解します。
pyplotは現在のFigureやAxesを操作する状態ベースのインターフェースです。短い試行に便利ですが、複数の図を作る場合はオブジェクト指向形式との違いを理解します。 仕組みだけでなく、検証方法と運用上の注意も具体例で確認します。
pyplotの役割
matplotlib.pyplotは図の作成や表示を少ないコードで行う状態ベースのインターフェースです。対話シェルや短い例では便利ですが、現在操作しているFigureやAxesを内部状態で管理します。処理が長くなったり、複数の図を同時に扱ったりすると、意図した図と現在状態が一致しない問題が起こることがあります。pyplotの関数が何を返すのか、描画対象がどのAxesなのかを理解して使いましょう。大きなプログラムではFigureとAxesのオブジェクト指向インターフェースと比較し、明示性やテストのしやすさから使い分けます。
figureとsubplotsの使い方
plt.figureは新しいFigureを作り、plt.subplotsはFigureと一つ以上のAxesをまとめて作成します。単一のグラフでもsubplotsを使うとAxesを変数へ保持でき、タイトルや軸範囲を直接設定できます。複数の行列配置ではaxesの形が一つのAxesか配列かによって扱いが変わるため、squeezeの設定や返り値を確認してください。図番号を指定して既存Figureを再利用する場合、前回の描画が残っていないか確認します。各Figureに明確な役割を持たせ、必要な図を保存した後に閉じることで、状態の混同やメモリー使用量の増加を防ぎます。
pyplot関数で描画する
plt.plot、plt.scatter、plt.histなどは、現在のAxesへ描画を追加します。短いスクリプトでは読みやすい一方、どのAxesが現在の対象なのかは、直前のFigure操作に依存します。別の図を作った後で前の図に追加したつもりが、現在の図へ描画することがあります。複数のグラフを作るときは、現在状態を切り替える操作と描画の順番を明確にし、各図の出力を確認してください。系列の値、ラベル、凡例を追加する際も、直近の描画だけを前提にしないで、図の構成を記録してテストできる形にします。
現在のAxesを明示する
pyplotではgcaなどが現在のAxesを返し、そのオブジェクトへメソッドを呼ぶことができます。状態ベースの関数を使い続ける場合も、Axesを変数に保存して利用すれば対象を明示しやすくなります。例えばax.set_titleやax.set_xlabelのようなメソッドは、どの領域を変更するかコードから分かります。関数間で現在状態を暗黙に共有すると、予想外の副作用や順序依存が生じます。現在状態を切り替える操作は最小限にし、描画処理の開始時に対象を決めます。表示と保存を行う関数の責務を分けると、図を変更せずに別出力へ再利用できます。
FigureとAxesを使った書き換え
既存のpyplot例は、fig, ax = plt.subplots()とした上でax.plotやax.setなどへ置き換えられます。Figureオブジェクトはsavefigやtight_layoutを担当し、Axesは系列、ラベル、目盛りなどの領域設定を担当します。役割を分けると、複数サブプロットを扱うコードの読みやすさが向上します。戻り値が複数のAxesになる場合は、変数名を単数と複数で分け、配列の次元を確認してください。pyplot形式から移行するときは、描画だけでなく現在Figureの切替や表示順序も見直し、出力が以前と同じ意味を保っているか画像とデータ値で確かめます。
サブプロットで複数系列を整理する
plt.subplotsの行数と列数を指定すると、一つのFigureに複数Axesを配置できます。比較する系列の単位や軸範囲が共通なら共有軸を使うと差を読みやすくできますが、尺度が異なる量を同じ軸に置かないようにします。各Axesには独立したタイトルやラベルを付け、必要に応じてFigure全体のタイトルを加えます。系列の順序や色を全サブプロットで統一すると比較しやすくなります。Axes配列のインデックスを誤ると別の図に描画されるため、配置と変数の対応を小さな例で確認してください。空いている領域に凡例や注釈を置く際もデータを隠さないようにします。
表示と保存を使い分ける
plt.showは対話的な確認に使い、Figure.savefigはファイル出力に使います。サーバー上のバッチ処理ではGUIが利用できないことがあるため、表示に依存しない保存経路を設計します。showの前後でFigureを閉じる挙動は環境やバックエンドによって異なるため、保存したい場合は順序を意識してください。出力形式、dpi、余白、ファイル名を明示し、古いファイルが残っているだけで成功と判断しないようにします。保存後に画像を開き、内容を確認する工程を設けます。画像の生成に失敗した場合は、処理を成功として報告せず、例外や出力先を調べます。
Figureを閉じて資源を解放する
pyplotは作成したFigureを管理するため、多数の図を連続生成すると閉じるまでメモリー上に保持されることがあります。plt.close(fig)で指定したFigureを閉じ、すべての図を終了する必要がある場合はclose allを使います。後者は他の処理が使う図まで閉じる可能性があるため、共有コードでは対象を明示してください。try/finallyを使えば保存処理で例外が起きた場合にも後始末を実行できます。閉じる前に必要な出力を完了したか確認します。大量生成の前後でメモリーや開いているFigure数を監視し、処理が継続しても資源が増え続けないことを検証します。
インタラクティブモードの注意点
インタラクティブモードでは描画を追加するたびに画面が更新され、NotebookやGUIで操作しながら探索できます。大量の点を繰り返し描くと更新コストが増えるため、必要な場合だけ再描画を行います。Notebookはセルごとに出力を保持するため、同じ図を何度も実行すると出力が重複することがあります。再実行可能なセルにし、入力データや設定を明示して、実行順に依存しないノートブックを作りましょう。対話的な探索で見つけた設定を最終コードへ移す際は、図の状態に頼らず必要な値をすべて記述します。画面上の結果と保存ファイルの結果が一致するか確認します。
バックエンドを意識する
Matplotlibバックエンドは描画結果を画面や画像へ出力する仕組みを選びます。GUIバックエンドはウィンドウ表示を提供し、非対話型のバックエンドは画像ファイル生成に適しています。環境変数や設定ファイルにより選択が変わるため、特定の開発PCだけで動くときはバックエンドと依存するGUIライブラリーを確認してください。バックエンドの切替はpyplotを読み込む前に必要となることがあります。コードの各所で何度も切り替えるのではなく、アプリケーション起動時に一貫して設定します。CIのような画面のない環境で小さな保存テストを実行すると、配布前に問題を見つけやすくなります。
テスト可能な描画関数を作る
描画コードを関数にまとめると、入力値と出力を切り分けて試験できます。関数はFigureやAxesを返す、あるいは出力先へ保存するなど、呼び出し側が期待する契約を明確にします。データが空、長さが異なる、欠損がある場合に例外となるのか、説明付きの図を生成するのかを決めてください。画像全体のバイト列比較はフォントや環境差に弱いため、系列データ、ラベル、軸範囲、保存ファイルの形式を検査する方法を検討します。試験後にFigureを閉じ、他のテストに状態が漏れないようにします。描画以外のデータ加工は別関数に分けると、数値結果も独立に検証できます。
練習課題:状態ベースとAxes形式を比べる
同じ三系列の測定データを、pyplotの状態ベース形式とFigure・Axes形式で描画してください。各例でFigure、Axes、系列のラベルがどのように管理されているか記録し、二つのFigureを同時に作って保存する処理も試します。図を連続生成するループを実行し、すべてのFigureが閉じられているか確認してください。画面のない環境でPNGを出力し、保存失敗が正常終了に見えないことも検証します。コードを関数へ移し、テストから系列数と軸ラベルを確認できる形に整理します。どの書き方を選んだかは好みだけでなく、状態の明示性、再利用性、保守の容易さを根拠に説明します。
コード例
手元のPython環境に貼り付ける前に、使用しているPythonの版と対象ライブラリの対応を確認してください。
import matplotlib.pyplot as plt
plt.figure()
plt.plot([1, 2, 3], [2, 4, 3])
plt.title("試験結果")
plt.show()手を動かす課題
同じグラフをpyplot形式とAxes形式で作り、複数図の管理やテストのしやすさを比較してください。