D3.jsを利用して棒グラフを作成する手順をまとめておきます。
今回は、前にGoogleChartsを利用した棒グラフを作成したときの気温データを使いましょう。
準備:データリストの作成
var data = [ ["date","tempmax","tempmin"], ["12/11",12.8,7.3], ["12/12",13.2,7.9], ["12/13",14.9,4.1], ["12/14",11.2,4.6], ["12/15",11.4,2.8], ["12/16",11.9,5.4], ["12/17",12,7], ["12/18",8.8,3.6], ["12/19",7.6,3.7], ["12/20",9.4,3.3], ["12/21",11,2.8], ["12/22",11.4,5.5], ["12/23",8.4,4.4], ["12/24",12.5,4.5], ["12/25",10.3,3.3], ["12/26",10,3.4], ["12/27",9.4,5.1], ["12/28",9.3,2.7], ["12/29",9.5,0.5], ["12/30",10.5,0.6], ["12/31",12.7,1.3], ["1/1",15.5,3.1], ["1/2",12.1,3.1], ["1/3",8.5,3.8], ["1/4",11.7,2.4], ["1/5",7.3,3.9], ["1/6",10.5,2.1], ["1/7",9.9,1.9], ["1/8",12.8,2.8], ["1/9",11.8,3], ["1/10",6.8,1.4], ["1/11",9,0.7] ];
GoogleChartsを利用したときの同じデータです。他次元配列になっていて、上位の配列の0番目の要素にラベルが格納されています。
D3.jsを利用して棒グラフを書く場合、データを棒の高さに関連付ける以外にたくさんの作業が必要です。
1.SVGオブジェクトを作る
2.縦軸と横軸を作る
3.データを表現する棒を作る
SVGオブジェクトを作る
グラフをのせるステージとしてSVGオブジェクトを設定します。
var width = 400; var height = 300; var margin = 50; var svg = d3.select("#base").append("svg") .attr("width",function(){return width + (margin * 2);}) .attr("height",function(){return height + (margin * 2);});
widthとheightがグラフエリアの幅と高さ、marginはグラフエリアの余白の幅をあらわしています。
縦軸と横軸を作る
var xScale = d3.scale.linear().range([0,width]); var yScale = d3.scale.linear().range([height,0]);
linear()というのは各軸が等間隔のスケールを仮定する場合に使います。今回の例の場合、X軸が日付データなので.ordinal()も利用できます。rangeはsvg上の座標の最小値と最大値です。y軸で最大値、最小値となっているところがポイント。y座標の値は、画面の上端で0、下にさがるほど値が増えるので0が一番大きくなるわけです。
var xScalelist = []; data.forEach(function(d){ xScalelist.push(d[0]); return; }); var yScalelist = []; data.forEach(function(d){ yScalelist.push(+d[1]); return; });
データをスケールに割り振るため、配列に格納します。
xScalelist.splice(0,1); yScalelist.splice(0,1);
0番目の要素であるラベルを軸用のリストから削除しておきます。
var yScalemax = d3.max(yScalelist); xScale.domain([0,xScalelist.length]); yScale.domain([0,yScalemax]);
x軸の値の範囲(domainで指定)は0からリストの長さ分です。y軸は値の最大値を軸の最大値にしました。(少し余裕をもたせても良いかもしれないです)
var xAxis = d3.svg.axis().scale(xScale).orient("bottom") .tickValues([0,1,2,3,4,5,6,7,8,9,10,11,12,13 ,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]) .tickFormat(function(d,i){return xScalelist[i]}); var yAxis = d3.svg.axis().scale(yScale).orient("left");
x軸につけるラベルは原始的ですが、1から数字を割り振ってしまいました。他に方法があるはずですね。
y軸はそのまま軸に値を関連付けます。
svg.append("g").attr("class","axis") .attr("transform","translate(" + margin + ", " + (margin + height) + ")") .call(xAxis); svg.append("g").attr("class","axis") .attr("transform","translate(" + margin + ", " + margin + ")") .call(yAxis);
そして、軸をsvgに貼り付けます。translateで位置を調整しています。
データを表現する棒を作る
y座標の値の割り振り方がポイントです。
var bars = svg.append("g").attr("class","rect").selectAll("rect") .data(yScalelist).enter().append("rect") .attr("height",function(d){return height - yScale(d);}) .attr("y", function(d){return (yScale(d));}) .attr("width",function(){return ((width/yScalelist.length)-0.1);}) .attr("x", function(d,i){return i * (width/yScalelist.length);}) .attr("transform","translate(" + margin + ", " + (margin) + ")");
svgオブジェクトの上端が0なので、y軸で示すための値をsvgの高さから引いたものがデータを示す棒の上端の位置になります。長方形の横幅は、軸全体の長さをデータ数で割った値にしてあります。こうするとピッタリと収まります。
ここまでをまとめると以下のようになります。
まとめ:凝ったグラフにしたければD3.js。データの傾向を見たいだけならGoogleCharts。
単純な棒グラフでも、ここまでの作業を必要とするので、グラフ作成にかなり時間がかかります。なので、手軽にデータ全体の傾向を見たければ、GoogleChartsを利用した方がいいでしょう。より複雑なグラフや、ちょっとした位置の変更をしたいような場合には、D3.jsの方が便利です。また、軸の設定や凡例の設置などは、一度きちんと動くコードを作成すれば、再利用ができます。