Tech Sketch Bucket of Technical Chips by TIS Inc.

D3.jsをつかってData-Drivenにリッチなグラフやチャートを作成しよう

Pocket

Webやスマートデバイス、センサーなどあらゆるものから情報を収集出来るようになり、世の中には膨大なデータが溢れかえっています。
また、ビッグデータやデータサイエンティストといったキーワードに注目が集まり、データ活用への期待が高まっています。しかし、単純に収集したデータはそのままでは見づらく、そこから意味を汲み取るのは困難です。

そこで、データの見せ方や伝え方が重要になってきます。
インフォグラフィックスやデータビジュアライゼーションといったキーワードにも注目が集まりつつありますね。

本記事ではD3.jsというJavaScriptのライブラリを利用し、このブログ(Teck-Sketch)のはてなブックマーク数や、世界の国別の人口の比較を視覚的に分かりやすく表現していきたいと思います。


インフォグラフィックス?データビジュアライゼーション?

キーワードとしてインフォグラフィックスとデータビジュアライゼーションを挙げました。両者とも複雑な内容を視覚的にわかりやすく伝えることに主眼を置いていますが、目的や用途が異なっていますので簡単に紹介したいと思います。

インフォグラフィックス

  • 既に整理され、分析されたデータを利用する
  • デザイナーにより、人の意図を通して作成される
  • データの更新があれば再作成が必要
  • 伝えたい内容にフォーカスしている

例:南アフリカワールドカップ(2010年)の事前予想

外れましたね!優勝スペイン、準優勝オランダでした。来年のワールドカップ楽しみですね!

データビジュアライゼーション

  • 整理されていない複雑なデータを扱う
  • コンピュータにより、アルゴリズムを通して作成される
  • データの更新があっても表示可能
  • データにフォーカスしている

例:世界のサッカー選手の関係を表すデータビジュアライゼーション

長友とサネッティは仲良し!(記事公開時点では!)

本記事で行っているのはデータビジュアライゼーションの方です。

インフォグラフィックスの作成やデータビジュアライゼーションを行う場合は以下のサイトが参考になります。眺めるだけで楽しいのでオススメです。

と、単語の説明が長くなってしまいましたが、以下で今回作成したサンプルの説明をしていきます。

D3.js

D3.jpg

今回作成したサンプルは、 D3.js というJavaScriptのライブラリを利用しています。D3.jsはデータに基づいたDOM操作とsvgによるグラフ描画が特徴です。 修正BSDライセンス で提供されているので、商用利用も可能です。

どんなことが出来るの?と思った方はまず、D3.jsの Gallery を覗いてみてください。豊富なサンプルが表示されるのでイメージがつきやすいと思います。
また、D3.jsでグラフやチャートを作成する際にsvgを使用するため、参照する際は最新のモダンブラウザか、IEであれば9以上をご利用ください。

Tech-Sketchの記事についたはてブ数をバブルチャート、ワードクラウドで表示する

最近Tech-Sketchに記事を書くようになったのですが、誰の、どんな記事が人気なのか気になっていました。今後どんな記事を書いていくかの参考にする為にも調べてみます。

データ準備

D3.jsで表示する為の元データをTech-Sketchをスクレイピングして取得します。
ブログからは執筆者、記事のタイトル、URLを取得し、そのURLを元に はてなブックマークのAPI を利用し、はてなブックマーク数を取得しました。

スクレイピングはRubyで Nokogiri を利用して行いました。ちょっとWebページをスクレイピングしてデータを取得したいときに、簡単に利用出来て便利ですね。Nokogiriについては 本家サイトのチュートリアル やAPIをご参照ください。
以下がスクレイピングに利用したコードになります。

処理としては、Nokogiri::HTMLでTech−SketchのHTML(Nokogiri::HTML::Document)を取得し、そこからcssメソッドでセレクタ指定し執筆者のアーカイブページへのリンク一覧のみを取得。
再度 Nokogiri::HTML(open(執筆者のアーカイブページのURL)) で執筆者のアーカイブページのHTMLを取得して、そこから記事のタイトル、URLを取得しました。
取得した記事のURLをはてなブックマーク取得用のAPIに渡し、はてなブックマーク数を取得しています。

単純にはてなブックマーク数取得用のAPIを呼び出しているだけですが、0件の場合は空文字列が返却される為、to_iメソッドを用いて整数型に変換しています。("".to_i #=> 0)

データ

以下は1件だけ抜粋し、整形したものになります。1階層目はデータのタイトル、2階層目は執筆者、3階層目は記事名、URL、はてなブックマーク数です。

バブルチャートで表示

データの準備が出来ましたので、表示してみます。
D3.jsのサンプルの バブルチャート が綺麗だったので、少し手を加えてみました。
執筆者毎に色分けされ、記事毎に円が作成されています。円の大きさがはてなブックマーク数によって変化するようになっています。最近公開された関数型プログラミング関連の記事で松井さん(薄紫色)の陣地が急拡大していますね。

bubble_chart.jpg

実際のコードは、D3.jsのサンプルに少し修正を加えた程度です。逆に、コードに合わせてデータを作成した部分もあったりしますが、その部分については後ほど説明します。
以下のコードはJSONを読込み、svgを作成している箇所になります。

コードを見てみると、D3.jsを知らなくても比較的読みやすいのではないでしょうか。通常のDOM操作ではなく、D3.jsのセレクションと呼ばれるノードセットに対してメソッドチェーンで操作している為、簡潔な記述になっています。
以下ではコード中に番号を振った箇所について簡単に説明していきます。

[1] レイアウトの設定

d3.layout.pack()で サークルパッキング (円を正方形に敷き詰める)用のレイアウトを設定しています。これにより、うまく重ならないように円を敷き詰めて配置することが出来ます。

[2] svgの追加

D3.jsのselectメソッドでbody要素(セレクション)を取得しています。通常のDOM操作だとdocument.getElementsByTagName("body")などで要素を取得し、いちいち状態の設定を行う必要があります。bodyタグは1件でしたが、複数件ある場合はループ処理が必要になり面倒です。
D3.jsではセレクションに対して、設定したい処理を続けて書いていけるので簡潔に記述することが出来ます。

[3] svgデータ作成

ranking.jsonを読込み、データを作成していきます。

[3-1] nodeデータ作成

selectAllで取得したnodeのセレクションに対しclasses関数で作成したデータを追加し、gタグの追加、位置情報の設定を行なっています。

[3-2] titleタグ追加

nodeに対して"Author: 執筆者名, Title: 記事のタイトル, Bookmarks: はてブ数"の形式でタイトルを追加しています。

[3-3] 円の作成

円を作成し、円に対して記事のリンクを追加しています。円の半径(d.r)は、nodeのvalueとlayoutのsizeからd3.layout.packが自動的に設定してくれます。valueは、後に説明するclasses関数により[3-1]で追加されています。実際は、はてなブックマーク数です。

[3-4] 記事のタイトル追加

円の中に記事のタイトルを追加しています。円から大きくはみ出過ぎないように文字数の調整も行なっています(結構はみ出てしまっていますが...)

[4] データ追加用配列作成関数

[3-1]で呼び出されている関数です。rootからnodeに向かって再帰的に、配列classesに対して子要素が存在しない要素のデータを追加します。ここでキー"value"に対してはてなブックマーク数を設定しているので、円のサイズが自動的に設定されます。
上「コードに合わせてデータを作成した」と述べましたが、この関数部分が該当します。どの階層もキーに"name"と"children"を設定することで、もっと深い階層や異なる階層のデータを表現することが可能になります。

ワードクラウドで表示

次は同じデータを違う形式で表示してみます。
同じようにはてなブックマーク数でサイズが変わるようなものが合うと思ったので、ワードクラウドで表示してみました。執筆者ごとに色分けしていないので大分カラフルな見た目ですね。ただ、バブルチャートよりは人気度合いの差が分かりづらいでしょうか。もっと差を目立たせるようにするには、文字サイズの設定部分で工夫する必要があります。

cloud_words.jpg

ワードクラウド形式で表示する際に d3-cloud というライブラリを利用しました。
こちらも サンプル を参考に、JSONから値を取得するように修正しています。バブルチャートと同様に、コード中に番号を振った箇所について簡単に説明していきます。

[1] JSONからワードクラウド作成用データ作成

AjaxでJSONを取得し、配列に対して記事のタイトル、URL、はてなブックマーク数を追加します。

[2] ワードクラウドの状態設定

色の設定、レイアウトの設定、文字の傾きや文字サイズの設定などを行なっています。文字サイズはレイアウトに収まるように Math.sqrt(d.size) * 8 の部分で微調整をかけています。レイアウトはcloudを設定しています。これにより、ワードクラウド用のレイアウトが適用され、文字が重ならないように配置されます。

[3] ワードクラウド作成

ワードクラウドの要素を追加していく処理になります。ポイントは、attr("transform", "translate(960, 540)")でレイアウトの中心に設定している部分です。これを設定しなかった場合は(0, 0)から描画されてしまい、右下1/4しか表示されなくなってしまいます。


ここまで、Tech-Sketchの記事についたはてブ数をバブルチャート、ワードクラウドなどの静的なグラフで表現してきました。以下ではD3.jsを使って動的な表現をしてみたいと思います。

世界人口を動的に分裂していくバブルチャートで表現する

世の中では世界人口は様々な方法を用いて表現されており、割とポピュラーな題材だったりします。例えば、棒グラフや折れ線グラフのような所謂普通のグラフであったり、世界地図に色をつけ人口を表したものだったりです。
そこで、地域⇒国へと円が分割していく、ちょっと変わった世界人口のバブルチャートを作成してみました。

2012年 世界人口グラフ

各地域(アジア、アフリカ、ヨーロッパ、北アメリカ、南アメリカ、アフリカ)毎にまとまって表示

world_population_A.JPG

ランダムに表示

world_population_B.JPG

機能紹介

このグラフには以下の機能があります。

  • 円にカーソルを乗せると情報表示
  • 円をクリックすると分割
  • 各地域毎の表示・非表示切替ボタン
  • 一括表示・非表示切替ボタン
  • 動作・停止の切替ボタン
  • 表示されている円の一括分割ボタン
  • 表示方法の切替ボタン

色々さわって表示を切り替えてみてください。

データ

グラフには、国連が提供している Total Population - Both Sexes2012年度 の人口データをJSONファイルに加工して使用しています。
以下は加工したJSONファイルを一部抜粋したものです。

コードの解説

以下ではソースコードの一部を抜粋し解説をしていきます。
完全なソースコードは こちら をご参照下さい。

[1] Circleクラス定義

Circleクラス定義になります。
Circleクラスが保持するインスタンスは以下になります。

addToField() svgにcircleエレメントを追加する
moveCircle() svg上の円を移動させる
checkCollisions() 特定の範囲内に描画されているか確認
attrStroke() 分割済み円に対する表示切替
splitCircle() クリック時に行う円分割処理
[2] 円の分割処理

splitCircle関数は、円クリック時に対象円をchildrenに分割する処理を行っています。
childCircle.addToField関数でsvgへの追加処理を、childCircle.circleTag.data関数ではエレメントに円クラスを紐付けています。
ここで円クラスを紐付けする事により、他の関数で円クラスが必要になった場合、circleエレメントさえ取得出来ればCircleクラスも使用可能になります。

[3] circleエレメント作成

addToField関数は、Circleクラスが保持しているデータを元にsvg上にcircleエレメントを作成しています。
作成方法はd3.select関数を使用しsvgエレメントを取得した後にappend関数で追加する形で作成しています。
また、各円毎にマウスオーバー・アウト処理を設定しています。
マウスオーバー時にはtextエレメントに国名(Circle.name)と人口(Circle.population)データを渡し画面左上に表示させます。
マウスアウト時にはtextエレメントそのものを非表示に切り替えています。
またtextエレメントは改行を行えないため、タグを内包させ、その中に国名・人口テキストを入れています。

[4] 親円の見た目変更処理

attrStroke関数は、分割処理を行った後の親円の見た目変更処理を行っています。
このグラフでは地域情報も表示したかったので、円を非表示にするのではなく、半透明化させ分割していない円との区別を付けられるようにしました。

TDD黄金の回転

ギアが噛み合って回転しているサンプル を眺めていたら何故かTDDの黄金の回転が思い浮かんだのでちょっと弄ってみました。(流行に乗って?フラットデザインです)
回転の向きや色を変えたくらいなのでコードの説明はしません。作ってみたかっただけです、はい。
通常はデータからどの表現が合うか考えてグラフやチャートを作成しますが、Galleryを眺めて使いたい表現から入るのも面白いですね。

TDD.jpg

まとめ

本記事ではD3.jsを使ったグラフ作成の例を紹介してきました。D3.jsを使うと簡単にリッチなグラフやチャートが作成できます。また、日本語ドキュメントやサンプルが豊富なのも嬉しいですね。ドットインストールにも追加されていますし、日本語のチュートリアルもありますので、学習もしやすいです。

ビッグデータやデータ分析の盛り上がりに合わせて、このようなグラフやチャート作成をする機会も増えてくると思います。その際に利用するライブラリとして、D3.jsは有効な選択肢となりえます。この機会に学習を開始してみてはいかがでしょうか?

本記事に続き、同じテーマであと2記事公開されます。
Highcharts.jsを利用したグラフ作成や、GoogleMap上へのグラフ描画、途中ArduinoやGoogle Chromeのシリアル通信APIなどに脱線しつつ盛りだくさんでお送りしますのでお楽しみに!

エンジニア採用中!私たちと一緒に働いてみませんか?