好きなJavascriptの可視化パッケージをRの世界にサクッと持ち込む(htmlwidgets)

追記(12/24):これでうまく動いたと思ってたんですが、まだRmarkdownではうまくグラフ描けないようです。。すみません。

追記(12/26):YAMLで指定するのをd3.jsではなくd3.min.jsに変えれば動くことが分かりました(.minもBowerがダウンロードしてくれてるのでパス変えるだけでOK)。原因は判明していますが、けっこう長くなりそうなので後日別の記事を書きます。。

追記(12/27):書きました → htmlwidgetsでD3.jsを使おうとしたら文字コードの闇に飲まれかけた話 - Technically, technophobic.

追記('15/01/02):pandoc側で修正が入ったので(Issue #1842)、minifyされてないファイルでもそのうち動くようになるはずです。


ここまでちょこまかと記事を書いてきましたが、いよいよ自分で可視化ライブラリをつくってみます。

今回は例としてmetrics-graphics.jsを使ってみます。こんな感じ↓のグラフがRで描けちゃいます!

f:id:yutannihilation:20141224225951p:plain

※metrics-graphics.jsは、ちょうど先ほどv2.0が出たところみたいです。

おさらい

htmlwidgetsはRからJavascriptの可視化ライブラリを使うためのフレームワーク的なもの。

htmlwidgets for R

Rのデータ形式Javascript側で必要なデータ形式が違うこともあるけど、その辺はなんとかがんばる。Javascript側で変換するユーティリティは用意されている。

プロジェクトをつくる

この辺は前回やったのとと同じです。 RStudioユーザのひとはFile > New Projectで新しいプロジェクトをつくりましょう。RStudioユーザでない人は、

devtools::create("metricsgraphics")
setwd("metricsgraphics")

しましょう。

Javascriptのライブラリを取ってくる

metrics-graphics.js は以下のファイルを適切に配置することで動きます。

  • D3.js
  • jQuery
  • metrics-graphics.js

さらにCSSも必要です(過去にはBootstrapも必要でしたが今は不要です)。

  • metrics-graphics.css

これをダウンロードしてきて metricsgraphics.yamlYAMLの魔法のような文法で書くことで...

...えっ?

なんか話違うことない? 「一瞬で」とかタイトルに書いてるのにけっこうめんどくさくない? やっぱり私のようなクリスマスイブにRのブログを読んでるようなムサい人間には可視化なんて無理だったんだ。ははは。

と心折れかけたそこのあなた! 諦めるのはまだ早いです。

Bowerをインストールする

そんな私たちに心強い味方がBowerというJavascriptのパッケージマネージャです。htmlwidgetsには、Bowerレポジトリにあるパッケージなら自動でいい感じに配置してくれるという素晴らしい機能があります。これは使うっきゃありません。

f:id:yutannihilation:20141224231854p:plain

(http://bower.io/docs/about/#logo)

インストール方法はたぶん、「Bower インストール Mac」とか「Bower インストール Windows」とかググればいい感じのページが出てくると思うのでここでは詳しく書きませんが、私はRStudioを動かしている環境がUbuntu 14.04なので、

sudo apt-get install nodejs nodejs-legacy npm
sudo npm install -g bower

と打てば入りました。(nodejs-legacyをインストールしているのはこういう問題への対応です)

ウィジェットのテンプレートをつくる

前回の記事では

htmlwidgets::scaffoldWidget("hoge")

ウィジェット名だけ書きましたが、scaffoldWidgetにはbowerPkgという引数を指定できます。ここにmetrics-graphics.jsのパッケージ名を指定してみます。

Bowerでのパッケージ名を調べる

Bower上でどんな名前で登録されているかはここ↓で検索できます。

Bower - Search

metrics-graphics.js の場合は、metrics-graphicsという名前のようです。

http://bower.io/search/?q=metrics-graphics

scaffoldWidget

さあ、いよいよコマンドを打ってみましょう。

htmlwidgets::scaffoldWidget("metricsgraphics", bowerPkg = "metrics-graphics")

すると、なにやらダウンロードしてるげな出力が出ます。

...snip...

metrics-graphics#2.0.0 inst/htmlwidgets/lib/metrics-graphics
├── d3#3.5.2
└── jquery#2.1.3

d3#3.5.2 inst/htmlwidgets/lib/d3

jquery#2.1.3 inst/htmlwidgets/lib/jquery
... Done! installing metrics-graphics
Created boilerplate for widget dependencies at inst/htmlwidgets/metricsgraphics.yaml

どうやら依存しているD3.jsやjQueryも自動でダウンロードしてくれています。

終わると、自動でmetricsgraphics.Rmetricsgraphics.yamlmetricsgraphics.jsができているはずです。ここでYAMLを見てみましょう。

dependencies:
- name: jquery
  version: 2.1.3
  src: htmlwidgets/lib/jquery
  script: dist/jquery.js
- name: d3
  version: 3.5.2
  src: htmlwidgets/lib/d3
  script: d3.js
- name: metrics-graphics
  version: 1.1.0
  src: htmlwidgets/lib/metrics-graphics
  script: dist/metricsgraphics.js
  style: dist/metricsgraphics.css

なんか分かりませんがいろいろ書いてます。srcに指定されているパスを見ると、JavascriptとかCSSが勝手に置かれています。便利! これを自分で書くのは大変そうですが、自動でやってくれるのいいですね。

※なぜかここではmetrics-graphicsのバージョンが1.1.0と表示されていますが、実際に入っているのは2.0です。

Rのコード

もとのコードはlist(message = message)にして渡すようにしていますが、データをそのままJavascriptに渡すようにします。

metricsgraphics <- function(data, width = NULL, height = NULL) {
  # create widget
  htmlwidgets::createWidget(
    name = 'metricsgraphics',
    data,
    width = width,
    height = height,
    package = 'metricsgraphics'
  )
}

Javascriptのコード

今回はとりあえずrenderValue()だけ実装します。

  renderValue: function(el, data, instance) {
    // convert data format to D3-friendly
    var data_d3 = HTMLWidgets.dataframeToD3(data);
    
    // convert date string to Date object
    var data_mg = MG.convert.date(data_d3, "date");
    
    MG.data_graphic({
        data: data_mg,
        target: '#' + el.id
    });

  },

ここを解説するには少しmetrics-graphics.jsのドキュメントを眺めないといけません。必要なところを引用します。

metrics-graphics.jsのグラフを描く関数

MG.data_graphic()にデータを渡せばグラフを描くことができます。指定できるパラメータの一覧は List of Options · mozilla/metrics-graphics Wiki · GitHubに書かれていますが、最低限datatargetを指定すれば大丈夫です。

data

dataには、想像通りグラフを描きたいデータを指定します。データ形式は以下のような形でなければなりません(Data · mozilla/metrics-graphics Wiki · GitHub参照)

[{'date':new Date('2014-11-01'),'value':12},
{'date':new Date('2014-11-02'),'value':18}]

data.frameのデータをこの形式にするには、htmlwidgetsが用意している関数HTMLWidgets.dataframeToD3()が使えます。(前回参照)

    var data_d3 = HTMLWidgets.dataframeToD3(data);

また、日付の部分を変換するのはmetrics-graphics.js側にMG.convert.date()という関数が用意されてるのでこれを使いましょう。

    var data_mg = MG.convert.date(data_d3, "date");

ちなみに、datevalueという要素名はそれぞれx-accessory-accessorというパラメータで指定できますが、今回はデフォルトの名前を使います。(Data · mozilla/metrics-graphics Wiki · GitHub参照)

target

target にはグラフを描くDOM要素を指定します。デフォルトだとvizというidを持つDOM要素にデータを表示します。(Graphic · mozilla/metrics-graphics Wiki · GitHub参照)

htmlwidgetsの場合は、renderValueの第一引数(上のコードだとel)にDOMが渡されるので、そのidを指定します。CSSセレクタの形式で書くのでidを指定する場合は#が必要な点に注意してください。

        target: '#' + el.id

ともあれ、これで完成です。Ctrl+Shift+Bでビルドします。

グラフを描いてみる

さっそく使ってみたいと思います。

使うデータ

wikipediatrendという、Wikipediaの各記事へのアクセス数の統計があるそうです。それを使ってみたいと思います。

Automated Data Collection with R - Introduction to Public Attention Analytics with Wikipediatrend

見てみるのは、今年話題だったこちらのキーワードです。 刺激惹起性多能性獲得細胞 - Wikipedia

Wikipedia上では「刺激惹起性多能性獲得細胞」という厳めしい名前になるそうです。漢字が多すぎてめまいが...

使ってみる

※Date型をうまく渡す方法はまだなさそうなので、as.characterを通して文字列として渡しています。

library(metricsgraphics)
library(wikipediatrend)
library(dplyr)
library(magrittr)

stap <- wp_trend("刺激惹起性多能性獲得細胞",
                 lang = "ja",
                 from="2014-01-01",
                 friendly = T)

stap %<>% transmute(date = as.character(date), value = count)

metricsgraphics(stap)

結果

すると、右下にこんなグラフが現れるはずです! マウスを重ねると値が出ます。

f:id:yutannihilation:20141225010906p:plain

細かい部分には手が届きませんが、だいたい思ったことができました。ほっ。

まとめ

ちょっと長くなってしまいましたが、今回やったことはこれだけです。

  1. Bowerをインストール
  2. bowerPkgを指定してscaffoldWidget()を実行すると、ウィジェットのひな形をつくるとともにJavascriptのライブラリを自動で配置してくれる
  3. RとJavascriptのコードをちょっといじる
  4. データを渡す

意外とお手軽なんですが、お手軽さが伝わったでしょうか...?

理解できていない部分も多々あるので、ツッコミ、分かりにくい部分などあればコメント欄なりTwitterなりでご指摘ください。

今回作ったコードは、とりあえずGithubに置きました。devtools::install_github("yutannihilation/metricsgraphics")すればインストールできるはずです。