Data Visualization meetup 2017
データビジュアライゼーションデータビジュアライゼーション
の作り方の作り方
/Masayuki Shimizu @_shimizu
1
群馬県高崎市在住
2015年11月に転職
日本経済新聞社メディア戦略部
DataViz/GIS エンジニア
自己紹介
清水正行清水正行
2 . 1
主なお仕事主なお仕事
2 . 2
日経:Visual Data
2 . 3
2 . 4
2 . 5
2 . 6
2 . 7
2 . 8
趣味趣味
2 . 9
Blog
2 . 10
本日の目録
VDataコンテンツの作り方D3.js
はまりどころZ-indexが効かない問題Pathのトランジション折り返さない問題
3
VDataコンテンツの作り方VDataコンテンツの作り方
4 . 1
制作フロー制作フロー
1. 企画発案(記者より)
2. データ収集・分析・整形
3. デザイン案やモックを作って打ち合わせ
4. デザイン決定
5. 実装
6. 宣伝用の素材等
(SNSに流す用のグラフィックスや動画など)
4 . 2
作成チーム
PM1人
デザイナー4人
エンジニア2人
2ライン(デザイナー1、エンジニア1)
作成期間(2週間~4週間)、速報(6時間)
一点物が多い
4 . 3
これらの条件を踏まえ、日経ビジュアルデータで
はD3.jsというライブラリを採用しています。
4 . 4
D3.jsD3.js
データビジュアライゼーションライブラリ
5 . 1
特徴
Data-Driven Document
デファクトスタンダード
チャートライブラリではない
学習コストが高いと言われている(誤解?)
5 . 2
D3 Gallery
5 . 3
D3.jsを使っても公式サイトのGalleryに掲載されて
いるような複雑なデータビジュアライゼーションが
簡単に作れるわけではありません。
5 . 4
忘れましょう。忘れましょう。
5 . 5
データビジュアライゼーションで必要になる作業
5 . 6
データを図表で表現する
5 . 7
Data -> Document
5 . 8
データの内容をエレメントの属性やスタイルに
反映する処理を繰り返す
5 . 9
面倒なこと面倒なこと
エレメントとデータのリレーション管理
トランジション
値の正規化や座標計算
5 . 10
D3は、データビジュアライゼーション作成の上で
面倒な処理を肩代わりしてくれる。
5 . 11
Data-Driven Document
var data = [{id:0, value:100}, {id:1, value:200}, {id:2, value:300
//選択した要素にデータを束縛する
const div = d3.selectAll("div").data(data, (d) => d.id)
//要素が足りない時は追加
const enterDiv = div.enter().append("div")
//要素が多すぎる時は削除
const exitDiv = div.exit().remove()
//アトリビュートの内容をアップデートする
div.merge(enterDiv).attr("width", d=> d.value )
5 . 12
複雑なデータになっても複雑なデータになっても
市区町村境界データ市区町村境界データ
GeoJSON
6MB
1755 Features
15795 Properties
5 . 13
操作は変わらない
const projection = d3.geoMercator()
.fitExtent([[0, 0], [1240, 800]], geojson)
const geoPath = d3.geoPath().projection(projection)
//path要素にデータを束縛する
const path = svg.selectAll("path").data(geojson.features)
//path要素が足りなければ追加する
const enterPath = path.enter().append("path")
//path要素が多すぎるなら削除する
const exitPath = path.exit().remove()
5 . 14
5 . 15
可視化
//人口が2万人以上・以下で塗り分ける
selector.attr("fill", d => (d.properties.pop > 20000) ? "green
//群馬県に所属する市区町村だけ赤く塗る
selecot.filter(d => d.properties.pref === "群馬県").attr("fill"
5 . 16
5 . 17
D3.jsはデータを基にエレメントを操作する機能と、
トランジションや計算処理など最低限の機能のみ
を提供する。自由度は高いが作り手側でやらなく
てはならないことも多い。
また、ブラウザ間の差異を埋めるような機能はな
い。
5 . 18
はまりどころ
6 . 1
z-indexが効かないz-indexが効かない
6 . 2
6 . 3
重なり合う要素が多い場合重なり合う要素が多い場合
6 . 4
対応策対応策
最初にレイヤーを作っておき、手前に出したいエレ
メントをコピーして表示する
<svg>
<g class="axisLayer"></g>
<g class="plotLayer">
<circle class="orgin">
</g>
<g class="overlay">
</g>
</svg>
<svg>
<g class="axisLayer"></g>
<g class="plotLayer">
<circle class="orgin">
</g>
<g class="overlay">
<circle class="copy"> // <!-- 他
</g>
</svg>
6 . 5
copy tipscopy tips
束縛されたデータもコピーしておく
var plotLayer = d3.select(".plotLayer")
var ovarlay = d3.select(".overlay")
plotLayer
.selectAll("rect")
.on("mouseover", copy(overlay))
function copy(layer){
return function(){
var node = d3.select(this).node()
var nodeName = node.nodeName
var nodeAttr = node.attributes
6 . 6
SAMPLESAMPLE
6 . 7
ポイントポイント
はじめにレイヤーの構成をしっかり決めておく
要素を並べ替えるより、コピーしてしまう方が
管理がしやすい
オリジナルの要素にバインドされているデータ
も一緒にコピーしておくと便利
6 . 8
pathトランジションpathトランジション
6 . 9
例えば地形を変形する場合例えば地形を変形する場合
6 . 10
問題点問題点
6 . 11
SAMPLESAMPLE
6 . 12
対応策対応策
頂点の数を揃える
function geo2square(coordinates, width, height) {
var centroid = d3.polygonCentroid(coordinates)
width = (width) ? width : 0 ;
height = (height) ? height : 0 ;
var p = []
var i = 0
var length = coordinates.length
var qtr = ~~(length/4)
var nScale = d3.scaleLinear().domain([0, qtr]).range([0, w
l d3 l i d i 0 idth
6 . 13
ポイントポイント
頂点数の多いpathに合わせて、調整する
行政区ポリゴンが複数のパスで作られている場
合は、面積を計算して一番大きなポリゴンを変
形させる
6 . 14
折り返さない問題折り返さない問題
6 . 15
問題点問題点
SVGには折り返すという機能がないため、レスポン
シブに対応するためにはリサイズのたびにすべて
の座標を再計算して更新する必要がある。
text要素も折り返しが効かないので、地味に困る。
6 . 16
対応策対応策
tspanで括る
var textArray = ["1行目、あ","2行目",
d3.select("svg").append("text")
.datum(textArray)
.attr("transform", "translate(10
.each(leftLinebreak)
function leftLinebreak(array){
d3.select(this).selectAll("t
.data(array)
.enter()
.append("tspan")
.attr("x", "0em")
" " f i (d
<text>
<tspan x="0em" y="0em">1行目、あ</tspa
<tspan x="0em" y="1em">2行目</tspan>
<tspan x="0em" y="2em">3行目あああああ
<tspan x="0em" y="3em">4行目あ</tspan
</text>
6 . 17
SAMPLESAMPLE
6 . 18
foreignObjectforeignObject
SVGの中にHTMLを埋め込める。折り返しも効く。
※ IE11未対応
<svg>
<foreignObject width="200" height="200">
<html>
<div style="width:100px">ああああああああああああああああああああああああ
</html>
</foreignObject>
</svg>
6 . 19
aout wrapaout wrap
JavaScriptでやってみた。
6 . 20
ポイントポイント
SVG要素のレスポンシブ対応は割と大変
scale()やviewBoxで対応できる場合もある
6 . 21
まとめまとめ
データの収集・整形なども含め、データビジュアライ
ゼーションを作成するには地味で泥臭い作業がと
ても重要です。
7 . 1
資料資料
Visual Data ~データや映像で体感:日本経済新
聞
D3.js - Data-Driven Documents
bl.ocks.org/shimizu - 今回使ったサンプルコード
7 . 2

Data Visualization meetup 2017