{rbokeh} で Bokeh を R から使いたい
はじめに
Bokeh
は Python 以外にも R, Scala, Julia 用のパッケージを提供している。パッケージといっても Python の Bokeh
と連携するものではなく、Bokeh
がブラウザでのレンダリングに使っている Bokeh.js
を各言語で扱えるようにするもののようだ。そのため、各パッケージはそれぞれ単体で利用できる。
うち、R 用のパッケージである {rbokeh}
を使ってみたい。R には {htmlwidgets}
を使った JavaScript 利用の可視化パッケージが多数提供されているが、数が多くて使い方が覚えられない。できれば {rbokeh}
だけを使いたい。また、Pythonと見た目が揃えられると嬉しい。
インストール
現時点で CRAN には公開されていないため、GitHub からインストールする。現時点のバージョンは 0.2.3.2。
install.packages('htmlwidgets') install.packages('devtools') library(devtools) devtools::install_github('bokeh/rbokeh')
データの準備
サンプルとして {ggplot2}
に含まれる mpg
データを利用する。単に {rbokeh}
を利用するだけなら {ggplot2}
は不要。
library(ggplot2) library(rbokeh) dim(mpg) # [1] 234 11 head(mpg) # manufacturer model displ year cyl trans drv cty hwy fl class # 1 audi a4 1.8 1999 4 auto(l5) f 18 29 p compact # 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p compact # 3 audi a4 2.0 2008 4 manual(m6) f 20 31 p compact # 4 audi a4 2.0 2008 4 auto(av) f 21 30 p compact # 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p compact # 6 audi a4 2.8 1999 6 manual(m5) f 18 26 p compact
基本的な操作
Python の Bokeh
は matplotlib
を連想させる API を持っているが、 {rbokeh}
は別の API ( {ggplot2}
や {ggvis}
に近い ) を持つ。そのため、API は言語ごとに覚える必要がある。
mpg
データの displ
列と hwy
列を利用して散布図を描画する。
figure() %>% ly_points(x = displ, y = hwy, data = mpg)
加えて、 class
列で色分けする。サイズの変更など、利用できるオプションは help(ly_points)
で確認できる。
figure() %>% ly_points(x = displ, y = hwy, color = class, data = mpg)
色名は文字列で指定することもできる。
figure() %>% ly_points(x = displ, y = hwy, color = 'red', data = mpg)
NSE と SE
{rbokeh}
では、{ggplot2}
のように NSE ( Non-standard evaluation )と SE ( Standard evaluation ) 用の関数を明示的に分けていない。そのため、一部のオプションは以下のようにSEでも動作する。
# scatter figure() %>% ly_points(x = 'displ', y = 'hwy', data = mpg) # 出力省略
が、 SE では動作しないものもあるため、現時点では NSE を使ったほうがよさそうだ。
# scatter figure() %>% ly_points(x = 'displ', y = 'hwy', color = 'class', data = mpg) # 以下にエラー nchar(opts[[fld]]) : 'nchar()' は文字ベクトルを要求します
平滑化 / 回帰直線の描画
R のモデルを関数に渡すことで描画できる。lowess
に対しては ly_lines
を、lm
に対しては ly_abline
を用いる。この使い分けはちょっと覚えにくい。
figure() %>% ly_points(x = displ, y = hwy, data = mpg) %>% ly_lines(lowess(mpg$displ, mpg$hwy), color = "red", type = 2) %>% ly_abline(lm(hwy ~ displ, data = mpg), type = 2)
サブプロット ( facet ) の描画
{htmlwidgets}
ブログ中の {rbokeh}
紹介記事 では、サブプロットを lapply
+ {pipeR}
を使って描画する例が記載されている。自分は {dplyr}
好きなので {dplyr}
でやりたい。
library(dplyr) mpg %>% dplyr::group_by(class) %>% dplyr::do(dummy = ly_points(figure(width = 200, height = 200), x = displ, y = hwy, data = ., size = 2)) %>% { as.list(.[['dummy']]) } %>% grid_plot(nrow = 3, ncol = 3, same_axes = TRUE )
様々なプロット
以降、{rbokeh}
で描画できるプロットを例示する。
箱ひげ図
figure() %>% ly_boxplot(x = drv, y = hwy, data = mpg)
ヒストグラム
figure() %>% ly_hist(x = hwy, data = mpg)
ヒストグラムをグループ別に描画するには少し手間が必要。グループ別に塗り分けるためのカラーパレットを用意し、Reduce
で各グループ別のヒストグラムを追加する。
library(scales) colors <- scales::hue_pal()(length(levels(mpg$class))) colors <- setNames(colors, levels(mpg$class)) colors # 2seater compact midsize minivan pickup subcompact suv # "#F8766D" "#C49A00" "#53B400" "#00C094" "#00B6EB" "#A58AFF" "#FB61D7" ghist <- function(fig, group) { ly_hist(fig, x = hwy, data = dplyr::filter(mpg, class == group), breaks = seq(10, 45, 5), color = colors[[group]]) } Reduce(ghist, levels(mpg$class), figure())
カーネル密度推定のプロット
グループ分けしたい場合はヒストグラム同様の処理が必要。
figure() %>% ly_density(x = hwy, data = mpg)
折れ線グラフ
df <- data.frame(x = c(1, 2, 3), y = c(4, 2, 5)) figure() %>% ly_lines(x = x, y = y, data = df)
地図
地図は {maps}
パッケージのデータを利用してプロットができる。
library(maps) figure() %>% ly_map("state", color = "gray")
また、 Google Maps を利用することもできる。
gmap(lat = 35.684, lng = 139.753, zoom = 15, map_type = 'terrain')
現在 (簡単には) できないもの
R でよく使う種類のプロットを優先しているせいか、以下のような基本的なプロットにはまだ対応していないようだ。
種類 | GitHub Issue | 備考 |
---|---|---|
棒グラフ | #8 | 頑張れば ly_hist で描ける。 |
エリアプロット | #10 | |
ヒートマップ | #86 | ly_hexbin はある。ly_image で近いことはできるが、軸のラベル付けが手間。 |
円/ドーナツ |
まとめ
{rbokeh}
、上に挙げた基本的なプロットが使えるようになれば実用できそうな感じだ。Bokeh.js
側には主要な可視化が揃っているため、他のパッケージと比べると利用範囲が広いこと、見た目を複数言語で揃えられるのがメリットかなと思う。