Flask / Django でグラフを書く

lockdefです

データサイエンスでお世話になってるmatplotlibのグラフをそのままウェブに出したいなと思いつきました
統計データから利用者の使用ブラウザや閲覧時間などをグラフで可視化するときに使えそうです

主にFlaskでの実装で説明しますが、Djangoの実装も最後のあたりに書いてあります。

必要なライブラリ

pip install flask
pip install matplotlib
pip install numpy
pip install seaborn

実装

タイトルにあまり関係ない部分は説明せずコードのみの紹介になります

from io import BytesIO
import base64

from flask import Flask, render_template
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

app = Flask(__name__)

今回はグラフを画像データに変換してHTMLで描写するので、imgタグのsrcで読み込める形にフォーマットします。

def img_format(byte):
    byte = base64.b64encode(byte.getvalue()).decode("utf-8") 
    img = "data:image/png;base64,{}".format(byte)
    return img

Flaskのルート設定です。
plt.savefigでメモリ上に画像を保存してimg_formatでHTMLで読み込める形に変換しています。

@app.route('/')
def index():
    byte = BytesIO()
    x = np.random.randn(1000)
    y = np.random.randn(1000)
    sns.jointplot(x, y)
    plt.savefig(byte)
    graph = img_format(byte)
    return render_template('index.html',
        graph=graph)

HTMLでは特別な部分はありません。
{{graph}}をimgタグのsrcに渡してあげるだけです。

<!DOCTYPE html>
<html>
<head>
    <title>Web Graph</title>
</head>
<body>
    <img src="{{ graph }}">
</body>
</html>

以上でグラフの描写は完了です。

全体コード

github.com

Djangoでの実装

HTMLは同じなのでviews.pyの紹介だけ行います。 コード内容はほとんど同じなので解説はFlaskのほうを参考にしてください。

from io import BytesIO
import base64

import django.shortcuts import render
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns


def img_format(byte):
    byte = base64.b64encode(byte.getvalue()).decode("utf-8") 
    img = "data:image/png;base64,{}".format(byte)
    return img


def index(request):
    byte = BytesIO()
    x = np.random.randn(1000)
    y = np.random.randn(1000)
    sns.jointplot(x, y)
    plt.savefig(byte)
    graph = img_format(byte)
    return render(request, 'index.html', {'graph': graph})