プロクラシスト

今日の寄り道 明日の近道

ipywidgetsとbokehで『jupyter』の更なる高みへ 【インタラクティブなグラフ描画】


スポンサーリンク

こんにちは、ほけきよです!

以前の記事でも、pythonのモジュールであるjupyterについて、その素晴らしさを熱く語りました。

今回は、jupyterの使いやすさを知った皆さんを更なる高みへと導くためのTipsです。

インタラクティブなグラフ表示方法がほしい!

jupyterのおかげで、pythonの実行がインタラクティブになり、 試行錯誤が飛躍的にしやすくなりました。

しかし、人間とは欲張りなもので、もっとかっちょよく、もっと扱いやすいUIがほしい!!と思うものです。

私もそうでした。私の欲は下記の二つです。

  • グラフ表示の際にパラメータインタラクティブ変えたい
  • グラフの座標などの情報インタラクティブ得たい
  • 何言っているかわかりにくいですね。実際に見てもらうほうが早い気がします。今回の完成系です

    f:id:imslotter:20170924025056g:plain

    よくないですか?

    今回は、この2つを実現するためのモジュール、ipywidgetsbokehを紹介します!

    ipywidgets

    上の図でのパラメータを変えるスライダーをjupyter上で実装できるようにするモジュール

    コレのおかげで、直感的にパラメータ操作ができるようになる。

    今回はスライダーだが、ほかにも

    など、用途に応じていろいろ設定可能。 ほかにどういうのがあるのかは、公式ページを見るのが良い。

    モデルのパラメータを調整するときなど、結構重宝する

    インストール方法

    • pip
    pip install ipywidgets
    jupyter nbextension enable --py widgetsnbextension
    • conda
    conda install -c conda-forge ipywidgets

    ※以前の私の記事( Windows10でpythonを使う環境を作る①:AnacondaとPycharm )を参考にanacondaを入れている人は、condaの方を入力してください!

    bokeh

    オシャレかつインタラクティブなグラフが書ける。かなり自由度が高く高機能である。↑の動画で見せたように、

    • グラフをぐりぐり動かしたり拡大縮小したりできる
    • グラフ上にポインタを置くと、 その点の情報を表示できる

    と、さながらjavascriptでのグラフと同じことができる優れもの。

    どんなことができるのかは、公式ページのGalleryをご覧になってみてください。

    インストール方法

    pipで一発です。

    pip install bokeh

    anacondaを導入している人はデフォルトで入っているようですね。

    ipywidgets & bokeh

    2つの役割と導入法が理解できたところで、次は2つをつなぎ合わせましょう

    要は

    スライドバーを動かすとグラフが動的に変わるし、グラフ内もぐりぐりと動かせるようにしたい!

    ってことです。

    コード

    詳しくはhokekiyooのgithubにもあげています*1が、ここでも。 jupyter notebookを開き、下記コードをコピペしてください。

    コードをみる
    from IPython.display import display
    import ipywidgets
    from bokeh.io import output_notebook, push_notebook
    from bokeh.plotting import figure, show, ColumnDataSource
    from bokeh.models import HoverTool,PanTool,WheelZoomTool,BoxZoomTool,ResetTool,UndoTool,RedoTool
    
    d = ipywidgets.FloatSlider(
        value=1, min=0, max=10.0, step=0.1)
    d.observe(on_value_change, names="value")
    
    hover = HoverTool(tooltips=[
        ("index:", "$index"),
        ("(x,y):", "($x,$y)")
    ])
    pan = PanTool() # 動かせるようにする
    wheel = WheelZoomTool() # マウスのスクロールでズーム
    box = BoxZoomTool() # 囲ったところをズーム
    undo = UndoTool() 
    redo = RedoTool()
    reset = ResetTool()
    x = np.linspace(0,1,101)
    y = np.sin(x*np.pi)
    source = ColumnDataSource(data=dict(x=x,y=y))
    
    
    # イベントハンドラ
    def on_value_change(change):
        alpha = change["new"]
        x = np.linspace(0,1,101)
        y = np.sin(alpha*x*np.pi)
        source.data = dict(x=x,y=y)
        push_notebook(handle=t)    
    
    
    
    
    fig = figure(width=640, height=400, tools=[hover,box,pan,wheel,undo,redo,reset], title="demo")
    r = fig.line("x", "y", source=source)
    output_notebook()
    display(d)
    t = show(fig, notebook_handle=True)
    
    • ipywidgetsでスライダーを設定
    • bokehのインタラクティブツールを設定(hover, pan, wheelなど)
    • on_value_changeで、値を変えたときに描画をし直すコールバック関数を書いておく

    これでOKです。 少しややこしいところもありますが、うまく使えるとかなり重宝するので、是非是非試してみてください。

    デモ

    こんなこともできます!

    f:id:imslotter:20170924120048g:plain

    裏で計算が走っているので重いですが、関連する記事の類似度に応じて記事をプロットしています。 パラメータを変えると、クラスタが現れたり!どの記事が近いってみなされてるんだろう~とか調べることができたり!

    自ブログの最適化にも活用していきたいところであります。

    類似記事抽出に関しては次記事で書く予定なのでお待ちください!ではではっ

    PythonとJavaScriptではじめるデータビジュアライゼーション

    PythonとJavaScriptではじめるデータビジュアライゼーション

    PROCRASIST