内容が古くなっている可能性がありますのでご注意下さい。
引き続きD3.jsを使用して横浜市の統計データをビジュアライズします。
今回は、表示するデータをユーザが選択できるようにします。
完成した画面は以下のようになります。
表示したいデータを青と赤のプルダウンリストで2つ選択することができます。この例では、緑被率と従業者数(その区で働く人の数)を表示しています。緑被率の高い区は従業者が少なく、従業者が多い区は緑被率が低いという大まかな傾向が見られます。
青と赤の棒グラフの目盛を、グラフの上下に表示しています。表示するデータの最大値に合わせて、スケールを自動的に変更するようにします。
こちらのHTMLファイルでは、実際にデータを選択して表示することができます。
まずはCSVのデータを用意します。
横浜市統計ポータルサイトからダウンロードしたExcelファイルから作成します。
ward,年少人口(H26),生産年齢人口(H26),老年人口(H26),夜間人口(H22),昼間人口(H22),就業者数(H22),従業者数(H21),緑被率(2009) 鶴見区,37070,186685,54335,272178,250323,132724,118174,13.7 神奈川区,26965,157892,47818,233429,233168,113520,127847,22.6 西区,10475,66760,18793,94867,170450,45980,165427,11.2 中区,15217,92544,31694,146033,243277,60977,203560,14.3 南区,20868,124191,47911,196153,154387,91476,49888,15.4 港南区,26837,135884,55027,221411,173691,101328,62810,22.9 保土ケ谷区,23711,129958,49513,206634,173514,94917,57714,31.1 旭区,30855,150559,66551,251086,197891,113501,60341,36 磯子区,19366,100645,41319,163237,136711,74474,56233,27.6 金沢区,25055,127348,50930,209274,195740,95645,81672,31.8 港北区,42268,233195,61276,329471,309610,160462,155079,26.5 緑区,25287,114337,38921,177631,146647,81590,45313,42.8 青葉区,44354,206375,56813,304297,234794,137185,77048,31.4 都筑区,36376,137709,31782,201271,193939,91660,101510,33.6 戸塚区,38325,172841,62205,274324,238630,127251,91840,37.8 栄区,16074,72895,33933,124866,97103,55035,27196,41.8 泉区,20515,94607,39143,155698,121197,69613,36794,39 瀬谷区,17266,76365,31710,126913,104258,56036,34436,35.1
1行目にはデータ系列名が入っています。
HTMLファイルのbody部のリストは以下のとおりです。
<body style="padding: 10px"> <select id="select1" onChange="drawChart();"></select> <select id="select2" onChange="drawChart();"></select> <br/><br/> <svg width="550px" height="550px"></svg> <script type="text/javascript"> var svg = d3.select("svg"); d3.csv("yokohama03.csv", function(data) { var options = []; for(var option in data[0]) { if(option != "ward") { options.push(option); } } d3.selectAll("select") .selectAll("option") .data(options) .enter() .append("option") .attr("value", function(d) { return d; }) .text(function(d) { return d; }); select1.options[0].selected = true; select2.options[0].selected = true; svg.selectAll("text") .data(data) .enter() .append("text") .text(function(d) { return d.ward; }) .attr("x", 0) .attr("y", function(d, i) { return (i * 25) + 66; }) .attr("font-size", "14px"); svg.append("g") .attr("class", "blue_axis"); svg.append("g") .attr("class", "red_axis"); svg.selectAll(".blue_rect") .data(data) .enter() .append("rect") .attr("class", "blue_rect"); svg.selectAll(".red_rect") .data(data) .enter() .append("rect") .attr("class", "red_rect"); }); drawChart(); function drawChart() { d3.csv("yokohama03.csv", function(data) { type1 = select1.options[select1.selectedIndex].value; type2 = select2.options[select2.selectedIndex].value; var scale1 = d3.scale.linear() .domain([0, d3.max(data, function(d) { return +d[type1]; })]) .range([0,450]); var scale2 = d3.scale.linear() .domain([0, d3.max(data, function(d) { return +d[type2]; })]) .range([0,450]); var axis1 = d3.svg.axis() .scale(scale1) .ticks(6) .orient("top"); var axis2 = d3.svg.axis() .scale(scale2) .ticks(6) .orient("bottom"); svg.select(".blue_axis") .attr("transform", "translate(80,40)") .call(axis1); svg.select(".red_axis") .attr("transform", "translate(80,505)") .call(axis2); svg.selectAll(".blue_rect") .data(data) .attr("x", 80) .attr("y", function(d, i) { return i * 25 + 50; }) .attr("fill", "RoyalBlue") .attr("height", "10px") .attr("width", function(d) { return scale1(d[type1]) + "px"; }); svg.selectAll(".red_rect") .data(data) .attr("x", 80) .attr("y", function(d, i) { return i * 25 + 60; }) .attr("fill", "OrangeRed") .attr("height", "10px") .attr("width", function(d) { return scale2(d[type2]) + "px"; }); }); }; </script> </body>
プルダウンリストのためのselect要素とグラフ描画のためのsvg要素はあらかじめ用意してありますが、ほとんどの描画はスクリプトで行います。まず、
var svg = d3.select("svg"); d3.csv("yokohama03.csv", function(data) {
svg要素を取得し、CSVファイル読み込みのコールバック処理で、
var options = []; for(var option in data[0]) { if(option != "ward") { options.push(option); } }
プルダウンリストに表示するデータ系列名の配列を作成します。さらに、
d3.selectAll("select") .selectAll("option") .data(options) .enter() .append("option") .attr("value", function(d) { return d; }) .text(function(d) { return d; }); select1.options[0].selected = true; select2.options[0].selected = true;
用意しておいた2つのselect要素をselectAll(“select”)で選択し、selectAll(“option”)でそれぞれのoption要素を選択します。option要素とデータ系列名の配列をバインドしますが、この時点ではoption要素はないのでenter()してからappend(“option”)でoption要素を追加し、value属性とテキストを設定します。
selectに対するループとoptionに対するループの、2重のループ処理を、D3独特の記法によって非常に簡潔に記述することができます。さらに、
svg.selectAll("text") .data(data) .enter() .append("text") .text(function(d) { return d.ward; }) .attr("x", 0) .attr("y", function(d, i) { return (i * 25) + 66; }) .attr("font-size", "14px");
行政区名のラベルと、
svg.append("g") .attr("class", "blue_axis"); svg.append("g") .attr("class", "red_axis");
目盛軸、
svg.selectAll(".blue_rect") .data(data) .enter() .append("rect") .attr("class", "blue_rect"); svg.selectAll(".red_rect") .data(data) .enter() .append("rect") .attr("class", "red_rect");
棒グラフのためのrect要素を作成します。
初期表示のために、
drawChart();
明示的にdrawChart()関数を呼び出します。drawChart()はselect要素のonChangeイベントでも呼ばれます。
drawChart()関数では、
d3.csv("yokohama03.csv", function(data) { type1 = select1.options[select1.selectedIndex].value; type2 = select2.options[select2.selectedIndex].value;
CSVファイルを読み込み、select要素で選択されているoptionの値を取得し、
var scale1 = d3.scale.linear() .domain([0, d3.max(data, function(d) { return +d[type1]; })]) .range([0,450]); var scale2 = d3.scale.linear() .domain([0, d3.max(data, function(d) { return +d[type2]; })]) .range([0,450]);
2つのグラフで使用するスケールを作成し、
var axis1 = d3.svg.axis() .scale(scale1) .ticks(6) .orient("top"); var axis2 = d3.svg.axis() .scale(scale2) .ticks(6) .orient("bottom"); svg.select(".blue_axis") .attr("transform", "translate(80,40)") .call(axis1); svg.select(".red_axis") .attr("transform", "translate(80,505)") .call(axis2);
目盛軸を描画します。ここでは、select(“.blue_axis”)のように、クラス名を指定して要素を選択しています。
最後に、
svg.selectAll(".blue_rect") .data(data) .attr("x", 80) .attr("y", function(d, i) { return i * 25 + 50; }) .attr("fill", "RoyalBlue") .attr("height", "10px") .attr("width", function(d) { return scale1(d[type1]) + "px"; }); svg.selectAll(".red_rect") .data(data) .attr("x", 80) .attr("y", function(d, i) { return i * 25 + 60; }) .attr("fill", "OrangeRed") .attr("height", "10px") .attr("width", function(d) { return scale2(d[type2]) + "px"; }); }); };
rect要素にサイズを設定して棒グラフを描画します。