Help us understand the problem. What is going on with this article?

matplotlibでリアルタイム描画

More than 3 years have passed since last update.

モチベーション

センサーとかの値を確認したり,機械学習の学習状況とかそんなんをリアルタイムにグラフにプロットしながら見たいときがある.
pythonにはmatplotlibっていう便利なグラフ作成ライブラリがあるのでこれを使いたい.

既知の問題とか

普通matplotlibでグラフを作るときは

import matplotlib.pyplot as plt

"""
plotしたいデータを計算する処理
...
"""
plt.plot(data)
plt.show()

とかやる.
だけど,show()を呼ぶとプログラムがそこでブロックされてリアルタイムな描画ができない.
調べてみるとshow()ではなくてdraw()を使おう!みたいな記事とか,Tkinter(tkinter)とかQtとかのGUIライブラリと組み合わせた方法とかがでてくるんだけど,Windows環境だとグラフに一度でも触るとGUIが固まったりしてとてもじゃないけど使えなかったりした.
(たしかMacとかのUnix環境だったら使えたような気がする.)

pause()を使おう!!!

例の如くstackoverflowにそれ関係のやりとりがあった.
参考: real-time plotting in while loop with matplotlib

結論はplt.show()の代わりにplt.pause(interval)を使うということ.
下に簡単なsin関数を永遠にplotする例を載っける.

注意点などはコメントに書いたので,読んでください.

matplotlib_realtime_plot_example.py
# -*- coding: utf-8 -*-
"""
matplotlibでリアルタイムプロットする例

無限にsin関数をplotし続ける
"""
from __future__ import unicode_literals, print_function

import numpy as np
import matplotlib.pyplot as plt


def pause_plot():
    fig, ax = plt.subplots(1, 1)
    x = np.arange(-np.pi, np.pi, 0.1)
    y = np.sin(x)
    # 初期化的に一度plotしなければならない
    # そのときplotしたオブジェクトを受け取る受け取る必要がある.
    # listが返ってくるので,注意
    lines, = ax.plot(x, y)

    # ここから無限にplotする
    while True:
        # plotデータの更新
        x += 0.1
        y = np.sin(x)

        # 描画データを更新するときにplot関数を使うと
        # lineオブジェクトが都度増えてしまうので,注意.
        #
        # 一番楽なのは上記で受け取ったlinesに対して
        # set_data()メソッドで描画データを更新する方法.
        lines.set_data(x, y)

        # set_data()を使うと軸とかは自動設定されないっぽいので,
        # 今回の例だとあっという間にsinカーブが描画範囲からいなくなる.
        # そのためx軸の範囲は適宜修正してやる必要がある.
        ax.set_xlim((x.min(), x.max()))

        # 一番のポイント
        # - plt.show() ブロッキングされてリアルタイムに描写できない
        # - plt.ion() + plt.draw() グラフウインドウが固まってプログラムが止まるから使えない
        # ----> plt.pause(interval) これを使う!!! 引数はsleep時間
        plt.pause(.01)

if __name__ == "__main__":
    pause_plot()

これで色々捗る!!!

おまけ

上で載っけたstackoverflowにdrawnowというパッケージを使った方法も載っているので紹介する.
drawnowpipで入るので

$ pip install drawnow

でOK.

使い方

matplotlib_drawnow_realtime_plot_example.py
# -*- coding: utf-8 -*-
"""
matplotlibでリアルタイムプロットする例

無限にsin関数をplotし続ける
"""
from __future__ import unicode_literals, print_function

import numpy as np
import matplotlib.pyplot as plt
from drawnow import drawnow, figure

def drawnow_plot():
    # drawnowパッケージに含まれているfigure関数を使って
    # figureオブジェクトを作る
    fig = figure()
    x = np.arange(-np.pi, np.pi, .1)
    y = np.sin(x)

    def draw():
        """
        drawnow関数に渡すplotに必要な処理を記述
        plotに必要な変数はこの関数がアクセスできるスコープの変数にしておく
        """
        plt.plot(x, y)

    while True:
        x += .1
        y = np.sin(x)
        drawnow(draw)

...書いてからソースコード見てみたが,drawnowは結局中でdraw()を呼んでるみたいで,Windowsでやると上手く行かなかった(GUIが固まる現象)...

結論

リアルタイムにプロットしたいときはplt.pause()を使おう!!!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした