テーブルのようにデータを利用しよう!ライブラリ「Bokeh」のデータソースオブジェクトを試してみた

データアナリティクス事業本部@札幌の佐藤です。
今回もBokehライブラリのチュートリアルを使って特徴を紹介できればと思います。

Bokeh Tutorial

今回は描画する上で便利なツールのひとつである、データソースオブジェクト「ColumnDataSource」についてです。

Jupyter Notebook上でグラフを表示させます。バージョンは最新の1.3.0です。

通常の描画

通常、データを描画する際に以下のようにXとYをそれぞれ事前に用意してあげる必要があります。

from bokeh.io import output_notebook, show
from bokeh.plotting import figure 
output_notebook()

x=[1, 2, 3, 4, 5] 
y=[6, 7, 2, 4, 5]
# グラフ全体の設定を行う
p = figure(plot_width=400,        #描画するグラフの横幅
           plot_height=400,       #描画するグラフの縦幅 
           title="散布図"         #グラフのタイトル 
          )

p.circle(x=x,                   #X軸。描画する変数を指定
         y=y,                   #Y軸。描画する変数を指定
         size=15,               #グラフに対しての直径値 
         line_color="navy",     #円の線の色 
         fill_color="orange",   #円の色
         fill_alpha=0.5         #円の透明度
        )

show(p) # 設定した内容を表示させます。

このくらいシンプルであれば特に問題はありません。
Bokehライブラリの特徴はPandasライブラリとの親和性の高さがありますので、いちいち df["hoge"] など書くのはちょっと煩わしいですよね。
また、複数の描画に対して実装したが後から df["hoge"] から data["hoge"] に変更された場合の改修工数もばかにならないと思います。

Bokehライブラリには、DBからデータを抽出する際にカラム名を指定するがごとく、列名を使用して抽出する手段があります。

それがデータソースオブジェクト「ColumnDataSource」です。

ColumnDataSourceを利用して描画してみる。

ColumnDataSourceに渡すことができるのは、辞書型やNumpy配列、PandasのDataFrameです。

まずは上の描画で記載した変数「x」と「y」を辞書型にして、 ColumnDataSource に渡してみます。
p.circlesourceColumnDataSource の変数、「x」と「y」を渡します。

from bokeh.io import output_notebook, show
from bokeh.plotting import figure
output_notebook()
from bokeh.models import ColumnDataSource    # ColumnDataSourceをimportする。

source = ColumnDataSource(data={
    'x' : [1, 2, 3, 4, 5],
    'y' : [6, 7, 2, 4, 5],
})                                            # 辞書型のデータを渡す

p = figure(plot_width=400, 
           plot_height=400)

p.circle('x', 
         'y', 
         size=20, 
         source=source)                       # 引数sourceにColumnDataSourceの変数をセット

show(p)

「x」と「y」を渡すだけで描画できました。

次にPandasのDataFrameを渡してみます。

#import bokeh.sampledata
#bokeh.sampledata.download()                        #サンプルデータのダウンロード
from bokeh.models import ColumnDataSource
from bokeh.sampledata.iris import flowers as df

サンプルデータを df.head(10) で先頭10件を確認します。

こんな感じのデータが入ってます。

source = ColumnDataSource(df)          # DataFrameを渡す
p = figure(plot_width=400, 
           plot_height=400)

p.circle('petal_length', 
         'petal_width', 
         source=source)                # 引数sourceにColumnDataSourceの変数をセット

show(p)

これも列名を入れてあげるだけで描画することができました。

ColumnDataSource を明示的に使用しなくても同様に行うことが可能です。
描画したいものに直接、辞書型やNumpy配列、PandasのDataFrameを渡すだけでOKです。

from bokeh.models import ColumnDataSource
from bokeh.sampledata.iris import flowers as df

p = figure(plot_width=400, 
           plot_height=400)

p.circle('petal_length', 
         'petal_width', 
         source=df)  # 引数sourceに直接DataFrameを渡す

show(p)

ColumnDataSourceの利点

ColumnDataSourceがないと描画できないのかというとNOです。なくても描画することは可能です。
ただ、これがあることでいいところもあって、そのひとつがツールチップが使用可能になる点だと思います。

from bokeh.models import ColumnDataSource
from bokeh.sampledata.iris import flowers as df

source = ColumnDataSource(df.head(10))
p = figure(plot_width=400, 
           plot_height=400, 
           tooltips="X軸:@petal_length / Y軸:@petal_width")     # ツールチップに表示させる情報

p.circle('petal_length', 
         'petal_width', 
         size=20, 
         source=source)  

show(p)

ColumnDataSource を使用していない場合、正しく値が表示されません。
(ツールチップ自体は ColumnDataSource を使用していなくても利用できます)

from bokeh.models import ColumnDataSource
from bokeh.sampledata.iris import flowers as df

df = df.head(10)
p = figure(plot_width=400, 
           plot_height=400, 
           tooltips="X軸:@petal_length / Y軸:@petal_width")     # ツールチップに表示させる情報

p.circle(df['petal_length'], 
         df['petal_width'], 
         size=20)  

show(p)

最後に

少しの手間でグラフに表示したい内容が増えるので、コードの分かりやすさ修正工数を考えても ColumnDataSource を利用していって問題ないかなともいました。