Flask matplotlibを使ってグラフを表示する方法(JavaScriptのChart.jsを使ってグラフを描画)
はじめに
今回はちょっと寄り道してFlaskでグラフを表示してみます。本当はグラフのアニメーションを作りたかったのですが諦めました。あとで調べたところ、JavaScriptを使ったほうが簡単できれいに出来るみたいだったのでそちらも作成してみました。
動作環境
Windows10
Python 3.7.5
Flask 1.1.1
コード
test.py
from flask import Flask, render_template, make_response from io import BytesIO import urllib from matplotlib.backends.backend_agg import FigureCanvasAgg from matplotlib.figure import Figure import matplotlib.pyplot as plt import random import numpy as np app = Flask(__name__) fig = plt.figure() ax = fig.add_subplot() x = [1, 2, 3, 4, 5, 6] y = [0, 1, 2, 3, 4, 5] @app.route('/') def index(): plt.cla() rand = random.randint(0, 5) y[rand] += 1 plt.title('sample') plt.bar(x, y) plt.legend() canvas = FigureCanvasAgg(fig) png_output = BytesIO() canvas.print_png(png_output) data = png_output.getvalue() response = make_response(data) response.headers['Content-Type'] = 'image/png' response.headers['Content-Length'] = len(data) return response if __name__ == "__main__": app.run()
解説
こちらを参考にさせていただきました。こちらで詳しい解説はされています。
簡単に説明すると、「plt」グラフを作成(描画はしていません)して「canvas」に画像を出力します。その画像データ「data」をレスポンス「response」で生成します。
png_output = BytesIO()
「BytesIO()」を使用すると普通はファイルに書き出す操作を省き仮想的にメモリ上に書き出すことができます。
data = png_output.getvalue()
バッファの全内容を含むバイト列を返します。
うーん、わかったようなわからないような(わかってない)。「グラフの画像データをメモリ上にバイト型データで渡して、また引っ張ってきて画像データに戻す」感じでしょうか。画像データをそのまま渡せたらいいのにと思ってしまいます。
とりあえずグラフを表示できました。
rand = random.randint(0, 5) y[rand] += 1
この2行が入っているのでページを更新(再表示)するとグラフの値が変化します。
plt.cla()
この1行が入らないと再表示するたびにグラフの色が変わっておもしろいです。
JavaScriptのChart.jsを使ってグラフを表示
次にhtmlで直接グラフを表示してみます。こちらがコードです。
test.html
<div class="chart-container" style="position: relative; width: 100%; height: 100%;"> <canvas id="myChart"></canvas> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"> </script> <script> var ctx = document.getElementById("myChart").getContext('2d'); var myBarChart = new Chart(ctx, { type: 'bar', data: { labels: ['1', '2', '6', '4', '5', '6'], datasets: [{ label: 'sample', data: [0, 1, 2, 3, 4, 5], backgroundColor: "rgba(0,0,255,0.8)" }] } }); </script>
結果はこちらです。
JavaScriptはまったく勉強していないので解説できません。JavaScriptでのグラフの書き方は、検索するといくらでも出てくると思いますので今回は省略させていただきます。
(<html><head><body><script>についてもまったくわからないので勉強します)
まとめ
今回はグラフを動かすことは出来なかったですが、表示の方法はなんとなくわかりました。ずっとPythonだけをしてきたのでmatplotlibを使った方法がしっくりきますが、JavaScriptで表示するほうが簡単な気もします。
Flaskを覚えるにはJavaScriptを知らないと難しそうです。Pythonは少し休憩してJavaScriptの勉強をはじめてみたくなりました。
↓よかったらポチッとしていってください。