【Python】Flask+MatplotlibでWebアプリにプロットしたグラフを表示する

webアプリケーション上でのグラフのプロット

webアプリケーションを作るうえで知っておきたいのがデータをプロットするテクニックですね。サイトに円グラフとかがあるとオシャレに見えます。

自分はReactやNode.jsは専門外なのでよく知りませんが、多分 JavaScript のライブラリでかっこいいグラフとかをひょいひょい作ってくれたりするのではないかなと思います。

ですが、Pythonでwebアプリーケーションを作るなら、やはりそのまま使い慣れた matplotlibで作ったグラフをwebアプリ上に表示させたいですよね。

そう思って今回はFlaskで作った簡単なhtml上にサーバー上でMatplotlibで作成したグラフを表示させる方法について色々模索したので、その結果を自分用に保存しておきます。

前提となるPythonの軽量Webアプリケーションフレームワークである「Flask」の使い方については以下の記事で解説しているのでそちらを参照してください。

FlaskとMatplotlibでwebアプリ上にプロットしたグラフを表示させる

サーバー上でMatplotlibを使って作ったグラフをhtmlで表示させる方法は大きく分けて2通りあります。

①生成した画像を画像データとしてレスポンスに返す

②内部ディレクトリにプロットした画像ファイル保存して、相対パスで呼び出す

画像ファイルを一時ファイルとして保存する方法はやってみたけどよく分からなかったというかpngをレスポンスにして返したら一発でできたので、また時間があるときに追記します。

画像データをレスポンスで返してhtml上にグラフを表示させたい場合は以下のように記述するとできます。インデントがおかしい場合はgitにコードを上げているのでそちらをダウンロードしてコピペしてください。

# ライブラリの読み込み
from flask import Flask, render_template, make_response, jsonify
from io import BytesIO
import urllib
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

# インスタンスの生成
app = Flask(__name__)

@app.route('/')
def index():
    return('<html><h1>実行結果</h1><p><p><img src="/graph1.png" ></img></html>')

@app.route('/graph1.png')
def graph1():
    # データからグラフをプロットする
    x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    y = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.title('サンプル')
    plt.grid(which='both')
    plt.legend()
    plt.plot(x, y)
    # canvasにプロットした画像を出力
    canvas = FigureCanvasAgg(fig)
    png_output = BytesIO()
    canvas.print_png(png_output)
    data = png_output.getvalue()
    # HTML側に渡すレスポンスを生成する
    response = make_response(data)
    response.headers['Content-Type'] = 'image/png'
    response.headers['Content-Length'] = len(data)
    return response


if __name__ == "__main__":
    app.run(debug=True)

参照:https://github.com/beginerSE/flask_plot_img/blob/master/app.py

plt.grid()plt.legend() はplt.plotでグラフをプロットするときによく使う関数です。Matplotlibの基本については以下の記事で解説しています。

‘/graph1.png’というルーティングで行っているサーバ内部の処理の流れとしては以下のような感じです。

  1. グラフをプロットする
  2. データをBytesIOでバッファに書き込む
  3. バッファに書き込んだバイト文字列に置き換えた画像データをレスポンスとして返す

BytesIOとは、Pythonで作ったバイナリデータをPCのバッファという一時的な保管庫に格納できるようにする関数で、標準ライブラリの io に中に含まれています。バイナリデータとは主に画像や音声などのデータのことです。

今のPCだと画像や音声はペイントやWindowsメディアプレーヤーなんかで、音声や画像として自動で表示されますが、内部的にはコンピューターで扱うデータは全てバイナリデータなのです。

バイナリデータでも文字として認識できるテキストデータと違って、音声や画像は内部(バイナリ)と外部見え方が余りにも違うため、テキストデータと対比して用いられ、一般的にバイナリデータ=画像・音声のバイナリデータを指します。例えば画像データなんかをバイナリとして開くと↓みたいな感じです

引用元:https://java2005.cis.k.hosei.ac.jp/materials/lecture22/binstream.html

PythonだとStringIOというライブラリでバッファに書き込んでいた人もいたのですが、自分の環境ではStringIOなりライブラリがなくpipでも見つからなかったので、BytesIOを使いました。

あとで知ったのですが。thinkerとThinkerみたいにPython2と3で名前が変わり呼び出し方が変わっていたみたいです。

関連記事:【Python】Pandasのデータフレームをテーブルに高速INSERTする

後はこの画像データをresponse.headers['Content-Type']で、リクエストが来た際に画像データ(png)だと宣言しておき、レスポンスが返されるURL(/graph1.png)をindex.html上で<img src=’/graph1.png’></img>を使って埋め込むとFlaskで動かしているwebアプリ上にMatplotlibで作成したグラフを表示させることができます。

 <htmlに画像のURLを埋め込む場合の例>

<img src="https:/ドメイン//graph1.png" alt=""></img>

終わり

Pythonでやった機械学習の結果をグラフなりで見やすく返すみたいなFlaskで作る個人レベルの簡単webアプリならこの処理で行けると思います。

ただMatplotlibのグラフはあまりオシャレではないので、見栄えなどを重視するのであれば、javascriptのChartJSなんかを使う方が一般的だと思います。

関連記事:Chartjsとcolorschemesでオシャレなグラフをプロットする

今回のプロットに使ったx,yのデータをデータベースから引っ張ってくる処理に変えると仕組み的にはそれっぽくなりますね。PythonのFlaskならsqlite3という簡易データベースが標準で用意されているので、それと連携させるとミニデータベースサイトが作れます

関連記事:【Python】スクレイピングした価格データをデータベース(DB)に保存する

関連記事:【Python】Flask+SQLAlchemyを使って、「ひとこと掲示板」を作る

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で



「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」

「エンジニアとして若いうちから高収入を得たい」



という強い気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする

   侍エンジニア塾       
侍エンジニアの無料体験レッスンを予約する -->