時系列データの可視化にはBokehがオススメ


はじめに

 時系列データを分析するにあたり、特に重要なのは「全体の俯瞰」と「詳細の注視」を行ったり来たりすることです。Pythonでよく用いられるmatplotlibは見た目が綺麗で便利ですが静的なグラフしか出力できません。そこで本記事ではBokehというライブラリを用いて、動的なグラフを作成しデータ分析を効率的に行う方法を紹介します!!!

Bokehとは

Bokehの公式ドキュメントの引用です
https://docs.bokeh.org/en/latest/index.html

Bokehはモダンなブラウザから操作できるインタラクティブな可視化ライブラリです。
Bokeh is an interactive visualization library for modern web browsers.

  BokehはJupyter notebook上でも利用が可能で、様々な動的なグラフを作成することができます。使い道は様々ですが、個人的には時系列データの可視化にとても効果的であると考えています。
  以下に公式デモのリンクです。「こんなことできるの?」というような動的な可視化ができるのでぜひ見てみてください。
https://demo.bokeh.org/

Bokehを用いた時系列データの可視化

  Jupyter notebook上で出力することを前提として、時系列データを可視化する方法を紹介します。データは水文水質データベースから取得した河川の水位データを利用します。
(このデータのWebスクレイピングの方法の記事はこちらです:https://qiita.com/Sampeipei/items/a22bba75acfbd01ac021)

CSVの読込み

import pandas as pd
import matplotlib.pyplot as plt

# CSVの読み込み
df_time_series_1 = pd.read_csv("../時系列データの可視化にBokehのススメ/time_series_data_1.csv", parse_dates=['date'], index_col='date')
df_time_series_2 = pd.read_csv("../時系列データの可視化にBokehのススメ/time_series_data_2.csv", parse_dates=['date'], index_col='date')

データの概要を取得します

print(df_time_series_1.info())
print()
print(df_time_series_2.info())
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 260832 entries, 1990-01-01 01:00:00 to 2020-01-02 00:00:00
Data columns (total 1 columns):
water_lev    260153 non-null float64
dtypes: float64(1)
memory usage: 4.0 MB
None

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 260832 entries, 1990-01-01 01:00:00 to 2020-01-02 00:00:00
Data columns (total 1 columns):
water_lev    258881 non-null float64
dtypes: float64(1)
memory usage: 4.0 MB
None

コンソールの出力からわかるようにデータは1990年1月から2020年1月までの30年間分で260832存在します。

以下にmatplotlibでの可視化した結果を示します

# matplotlibによる可視化
fig, ax_list = plt.subplots(1, 2, figsize=(12, 4))
df_time_series_1.plot(ax=ax_list[0])
df_time_series_2.plot(ax=ax_list[1], color='orange')

30年分もデータが存在すると混戦して何が起きているか判断がつきません。

Bokehによる可視化

  Bokehでの可視化を行うことで、データ好きな箇所で拡大・縮小をすることが可能です。しかもたったの数行で実行が可能です。はじめに1つでデータの可視化を行い、それを発展させて2つのデータを並べて、しかも両者のX軸が連動するようにします。

1つの時系列データの可視化

まずは必要なインポートです。(Anacondaに以下のライブラリが全て含まれているはずです。)

from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import ColumnDataSource
from bokeh.layouts import column

まずはDataFrameからBokehが解釈できるColumnDataSourceインスタンスを生成します

# DataFrameから可視化用のインスタンスを生成する
source = ColumnDataSource(df_time_series_1)

続いてBokehでデータ描画を行うためのfigureインスタンスを生成します。ここでX軸にdatetime型を指定しています。

# Bokehを描画するためのfigureインスタンスの生成。X軸の型にdatetimeを指定する。
bokeh_figure = figure(x_axis_type="datetime", plot_width=800, plot_height=400)

以下でfigureに表示させるデータとその描画方法を指定します。figureのlineメソッドを呼び出し、XとYの値をDataFrameのカラム名で指定します。

# figureインスタンスに描画するデータを指定する
bokeh_figure.line(x="date", y="water_lev", source=source, color="black", legend="time_seres_1")

これで描画に必要な定義は終了です。以下のコマンドで描画を実行します。最初の行がJupyter notebookでBokehの可視化を行うためのおまじないです。

# BokehをJupyter notebookで使用するためのおまじない
output_notebook()
# グラフの表示
show(bokeh_figure)

以下にJupyterに出力されたグラフの操作感をgifで示します。

ポイントは
1. X軸がdatetime型で扱うことが可能
2. 任意の箇所を拡大可能
3. スクロールでグラフの縮小・拡大が可能

このようなデータをmatplotlibで扱うと毎回時刻を指定して実行をくり返す必要がありますが、Bokehではそれがスムーズに直感的に行えます。

複数時系列データの可視化

  続いて複数のグラフを並べて表示する方法を紹介します。Bokehの素晴らしい所は並べたグラフのX軸(時間軸)を連動させることが可能な点です。

DataFrameからColumnDataSourceインスタンスをそれぞれ生成します。

# DataFrameから可視化用のインスタンスを生成する
source_1 = ColumnDataSource(df_time_series_1)
source_2 = ColumnDataSource(df_time_series_2)

Figrureインスタンスもグラフごとに生成します。

# Bokehを描画するためのfigureインスタンスの生成。X軸の型にdatetimeを指定する。
bokeh_figure_1 = figure(x_axis_type="datetime", plot_width=800, plot_height=200)
bokeh_figure_2 = figure(x_axis_type="datetime", plot_width=800, plot_height=200)

グラフ描画の線もそれぞれ生成しますが、色だけは別々にしています。

# figureインスタンスに描画するデータを指定する
bokeh_figure_1.line(x="date", y="water_lev", source=source_1, color="black", legend="time_seres_1")
bokeh_figure_2.line(x="date", y="water_lev", source=source_2, color="blue", legend="time_seres_2")

2つのグラフのX軸を共有するために以下のコードを書きます。片方のfigureインスタンスのx_range属性をもう一方に格納するという非常にシンプルな書き方です。

# bokeh_figure_1とbokeh_figure_2のx軸を共有
bokeh_figure_1.x_range = bokeh_figure_2.x_range

2つのグラフを縦に並べるためにcolumnインスタンスを生成します。引数に2つのfigureインスタンスを配列形式で渡す簡単な書き方です。最後にcolumnインスタンスをshow()に渡して描画が実行されます。

# BokehをJupyter notebookで使用するためのおまじない
output_notebook()
# bokeh_figure_1とbokeh_figure_2を縦方向に並べる
col = column([bokeh_figure_1, bokeh_figure_2])
# グラフの表示
show(col)

以下に出力のgifを示します

片方のグラフの表示位置を変更するともう一方のグラフが連動して動くことがわかります。このようにして複数の時系列データもまとめて可視化することができるため、Bokehは非常に便利です!!

まとめ

  Bokehを用いた時系列データの可視化を行ました。データは30年分の河川水位データを用いた、任意の箇所で拡大・縮小・移動ができることを示しました。このライブラリを用いることでデータ分析の効率が高まるだけでなく、他者に対しても説明性の高いデータ可視化ができると考えています。Bokehは他にも様々な動的グラフが作成可能ですのでぜひ調べてみてください。
https://docs.bokeh.org/en/latest/index.html
  ちなみに私はオンラインコースのDataCampでBokehの使い方を学びました。全部英語ですがデータサイエンスに必須のスキルが身につくので本当におすすめです!
https://www.datacamp.com/users/sign_in?redirect=https://learn.datacamp.com/
  最後に私のGithubのリンクを以下に貼って起きます!本記事のnotebookはここにあるのでよければチェックしてください
Visualizing_Time_Series_Data_With_Bokeh.ipynb