##前回作ったbokehのplotをhtmlに埋め込む
参考元:
https://www.udemy.com/the-python-mega-course/learn/v4/overview
bokehのチュートリアル:Embedding Plots
https://bokeh.pydata.org/en/latest/docs/user_guide/embed.html
bokhe.resourcesについて
https://bokeh.pydata.org/en/latest/docs/reference/resources.html
使うライブラリー:
from bokeh.embed import components
from bokeh.resources import CDN
##htmlに埋め込むための部品を取り出す
bokehで作ったplotをhtmlに埋め込むためには4つの部品が居る。
- bokehのplot情報。bokheを
show()
して表示されるhtmlで検証すれば確認できる。HTMLタグの<div class="bk-root">...</div>
ブロック。 - Javascriptブロック。HTMLタグでは
<script>
ブロック - cssのリンクURL
- javascriptのリンクURL
これら4つがあればhtmlにbokehのplot(グラフ)を埋め込むことができる。
plot元。前回の記事と全く同じ
from datetime import datetime as dt
from bokeh.plotting import figure, show, output_file
from pandas_datareader import data as pdr
import fix_yahoo_finance as yf
start = dt(2018,4,1)
end = dt(2018,7,31)
yf.pdr_override()
df=pdr.get_data_yahoo(tickers="FB", start=start, end=end)
def inc_dec(close, open_):
if close>open_:
value="Increase"
elif close<open_:
value="Decrease"
else:
value="Equal"
return value
df["Status"]=[inc_dec(c,o) for c,o in zip(df.Close, df.Open)]
df["Middle"]=(df.Close+df.Open)/2
df["Height"]=abs(df.Open-df.Close)
p=figure(x_axis_type="datetime", width=1000, height=300, title="Candlestick Chart", sizing_mode="scale_width")
p.grid.grid_line_alpha=0.3
p.segment(df.index, df.High, df.index, df.Low, color="black")
millisecond_of_12hour=12*60*60*1000
p.rect(df.index[df.Status=="Increase"], df.Middle[df.Status=="Increase"], millisecond_of_12hour, df.Height[df.Status=="Increase"],
fill_color="#CCFFFF", line_color="black")
p.rect(df.index[df.Status=="Decrease"], df.Middle[df.Status=="Decrease"], millisecond_of_12hour, df.Height[df.Status=="Decrease"],
fill_color="#FF3333", line_color="black")
output_file("Chandlestick Chart.html")
show(p)
from bokeh.embed import components
from bokeh.resources import CDN
script1, div1 = components(p)
script1
>>>
<script type="application/json" id=...
#すげぇ長いので以下略
</script>
div1
>>>
<div class="bk-root">
<div class="bk-plotdiv" id="65ac11b3-23d4-4103-8fde-209bf594f2f1"></div>
</div>
cdn_js=CDN.js_files
>>>
['https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.js',
'https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.js',
'https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.js',
'https://cdn.pydata.org/bokeh/release/bokeh-gl-0.12.13.min.js']
cdn_css=CDN.css_files
>>>
['https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css',
'https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css',
'https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css']
#今回はindex0のみ必要
cdn_js=CDN.js_files[0]
cdn_css=CDN.css_files[0]
-
components
メソッドにplotオブジェクトを渡せば、<script>
ブロックと、<div>
ブロック(plot情報)をstr
型で取得可能 - javascriptのリンクURLとcssのリンクURLは、htmlから直接コピペしてきてもいい。しかし、
CDN
で取得可能。CDN.js_files
ならjavascriptのURLがリストで得られる。widgetはスライダーなどを使ったplotなら必要。tableは表を使った場合。glは3Dグラフィックを使った場合に必要。今回はindex0のurlだけでおk。 - cssには
CDN.css_files
を使う - これら
script1
とdiv1
とcdn_js
とcdn_css
をhtmlに渡す。
##実際に表示させる
以前にflask
とvirtualenv
で作った仮想環境のhtmlに埋め込む。
htmlのコード全部をここに記述はしないが、重要なのだけ。
{%extends "layout.html"%}
{%block content%}
<link rel="stylesheet" href={{cdn_css | safe}} type="text/css" />
<script type="text/javascript" src={{cdn_js | safe}}></script>
<div class="plot">
<p>test for plot embeding</p>
</div>
{{script1 | safe}}
{{div1 | safe}}
{%endblock%}
-
{%extends "layout.html"%}
はflaskで別のhtmlコードを継承できる。{%block content%}
と{%endblock%}
のコードが挿入される。 -
{{ .py上の変数名 }}
で.pyがファイルの変数を受け取ることができる。cdn_css
、cdn_js
、script1
、div1
の4つ変数を受け取っている。flask
に付属してるjinja2
ライブラリーの機能。 -
{{|safe}}
の|safe
は文字列などのエスケープを無効にする。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/plot/')
def plot():
#venv。仮想環境上にここでimportされてるmodule全部入れなきゃ動かないぜ
import pandas as pd
from datetime import datetime
from bokeh.plotting import figure,show,output_file
pd.core.common.is_list_like = pd.api.types.is_list_like
from pandas_datareader import data as pdr
import fix_yahoo_finance as yf
#追加
from bokeh.embed import components
from bokeh.resources import CDN
start=datetime(2018,1,1)
end=datetime(2018,6,10)
yf.pdr_override()
#GOOG google
df=pdr.get_data_yahoo(tickers="GOOG",start=start,end=end)
def inc_dec(close, open_):
if close > open_:
value="Increase"
elif close < open_:
value="Decrease"
else:
value="Equal"
return value
df["Status"]=[inc_dec(c, o) for c, o in zip(df.Close, df.Open)]
df["Middle"]=(df.Open+df.Close)/2
df["Height"]=abs(df.Open-df.Close)
p=figure(x_axis_type="datetime", width=1000, height=300, title="Candlestick Chart", sizing_mode="scale_width")
p.grid.grid_line_alpha=0.3
p.segment(df.index, df.High, df.index, df.Low, color="black")
millisecond_of_hour12=12*60*60*1000
p.rect(df.index[df.Status=="Increase"],df.Middle[df.Status=="Increase"],millisecond_of_hour12,
df.Height[df.Status=="Increase"], fill_color="#CCFFFF", line_color="black")
p.rect(df.index[df.Status=="Decrease"],df.Middle[df.Status=="Decrease"],millisecond_of_hour12,
df.Height[df.Status=="Decrease"], fill_color="#FF3333", line_color="black")
#追加
script1, div1 = components(p)
cdn_js=CDN.js_files[0]
cdn_css=CDN.css_files[0]
return render_template("plot.html",
script1=script1,
div1=div1,
cdn_js=cdn_js,
cdn_css=cdn_css)
#output_file("CandileStick.html")
#show(p)
@app.route('/')
def home():
return render_template("home.html")
@app.route('/about/')
def about():
return render_template("about.html")
if __name__=="__main__":
app.run(debug=True)
flask
とvirtualenv
についてここではあまり触らない。
ただflask
はhtmlと.pyを繋げる。virtualenv
は仮想環境を構築できる。
-
pd.core.common.is_list_like = pd.api.types.is_list_like
は仮想環境上でpandas
を動かそうとするとエラーはく対策。pandasのversionが0.2~0.6だとエラーになるっぽい。v0.7で解決されるらしい。 参考元:stackoverflow :https://stackoverflow.com/questions/50394873/import-pandas-datareader-gives-importerror-cannot-import-name-is-list-like -
render_template
でtemplatesフォルダにあるhtmlがレンダリング(描写)される。ついでに4つの変数もhtmlに渡している。 - plot.htmlのURLにアクセスしたときに、bokehのplotが表示されるようになった
##あとがき
日本人はFlaskよりDjangoのほうが好き?