タイトルの通りです。CSVファイルを読み込んで、散布図を表示します。今回の記事の後半部分では、読み込んだ数値に合わせてグラフの縦軸、横軸の幅も対応させた散布図を作成します。
サンプルコードの実行結果はこちら
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>CSVファイルからデータを読み込んで散布図を表示する</title> <script src="../js/d3.js"></script> <style> svg{ width:360px; height:360px; border:2px solid red; padding:10px;} .mark{ fill:red; stroke:none;} .axis text{font-size:12px;} .axis path, .axis line{ fill:none; stroke:black; } .grid{ stroke: gray; stroke-dashaaray: 5,2; shape-rendering: crispEdges; } .tip{ position:absolute; top:0px; left:0px; z-index:10000; visibility:hidden; border:2px solid black; background-color:pink; width:96px; height:16px; overflow:hidden; text-align:center; font-size:10px; font-family:"メイリオ"; color:black; } </style> </head> <body> <h2>散布図を表示する</h2> <svg id="graph"></svg> <script src="test.js"></script> </body> </html> |
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
/* 散布図を表示する */ d3.csv("graphData.csv",function(error,data){ var svgEle = document.getElementById("graph"); var svgWidth = window.getComputedStyle(svgEle,null) .getPropertyValue("width"); var svgHeight = window.getComputedStyle(svgEle,null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); svgHeight = parseFloat( svgHeight ); var offsetX = 30; // X座標のずれ var offsetY = 20; // Y座標のずれ var svg = d3.select("#graph"); var arrData = []; data.forEach(function(d,i){ arrData.push([ d.xData * 1 , d.yData * 1, d.toolTipData * 1 ]); }); var circleElements = svg .selectAll("circle") // circle要素を追加 .data(arrData); circleElements .enter() .append("circle") // CSSクラスを指定 .attr("class","mark") /* アニメーション開始直前はグラウ中央に 赤い点があるようにする */ .attr("cx", svgWidth / 2 + offsetX ) // X座標の目盛りを中央にする .attr("cy", svgHeight / 2 - offsetY) // Y座標の目盛りを中央にする .attr("r",100) // 半径100の円 .attr("opacity",0) // 透明 .transition() // 設定後の座標までアニメーション .duration(2000) // アニメーションする時間 .ease("bounce") // バウンドする動きにする .attr("cx",function(d,i){ return d[0] + offsetX; // 1番目の要素をX表に指定 }) .attr("cy",function(d,i){ return svgHeight - d[1] - offsetY; // 2番目の要素をY座標に指定 }) .attr("r",4) // 点の半径 .attr("opacity", 1); function drawScale(){ var maxX = d3.max(arrData,function(d,i){ /* 以下のようにd[ ]の添字を0を指定すると X座標の最大値を求めることができます。 */ return d[0]; // X座標 }); var maxY = d3.max(arrData,function(d,i){ /* 以下のようにd[ ]の添字を1を指定すると Y座標の最大値を求めることができます。 */ return d[1]; // Y座標 }); // 縦の目盛りを表示するために縮尺設定 var yScale = /* 上記で求めた最大値maxYをここで使用する。 */ d3.scale.linear() // 縮尺設定 .domain([0, maxY]) // 元データの範囲 .range([maxY, 0]); // 実際の出力サイズ // 目盛りを表示 svg.append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - maxY - offsetY ) + ")" ) .call( d3.svg.axis() .scale(yScale) .orient("left") .ticks(20) ); // 横の目盛りを表示するために縮尺設定 var xScale = /* 上記で求めた最大値maxXをここで使用する。 */ d3.scale.linear() // 縮尺設定 .domain([0, maxX]) // 元データの範囲 .range([0, maxX]); // 実際の出力サイズ // 目盛りを表示 svg.append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - offsetY ) + ")" ) .call( d3.svg.axis() .scale(xScale) .orient("bottom") ); // グリッドを表示 var grid = svg.append("g"); // 横方向と縦方向のグリッド間隔を自動生成 var rangeX = d3.range(50, maxX, 50); var rangeY = d3.range(20, maxY, 20); // 縦方向のグリッドを作成 grid.selectAll("line.y") .data(rangeY) .enter() .append("line") .attr("class","grid") // (x1,y1) - (x2,y2) の座標値設定 .attr("x1", offsetX) .attr("y1", function(d,i){ return svgHeight - d - offsetY; }) .attr("x2", maxX + offsetX) .attr("y2", function(d,i){ return svgHeight - d - offsetY; }); // 横方向のグリッドを作成 grid.selectAll("line.x") .data(rangeX) .enter() .append("line") .attr("class","grid") // (x1,y1) - (x2,y2) の座標値設定 .attr("x1", function(d,i){ return d + offsetX; }) .attr("y1", svgHeight - offsetY) .attr("x2", function(d,i){ return d + offsetX; }) .attr("y2", svgHeight - offsetY - maxY); } // ツールチップを作成 var toolTip = d3.select("body") .append("div") .attr("class","tip"); // ツールチップを表示 circleElements .on("mouseover",function(d){ var x = parseInt( d[0] ); // 円のX座標 var y = parseInt( d[1] ); // 円のY座標 var data = d3.select(this).datum(); // 要素データを読み出す var dx = parseInt( data[0] ); // 円のX座標。変数xと同じ値 var dy = parseInt( data[1] ); // 円のY座標。変数yと同じ値 var t = parseInt(data[2]); // toolTipDataの値を格納する toolTip .style("left", offsetX + x + "px" ) // ツールチップのX座標 .style("top", svgHeight + offsetY - y + "px") // ツールチップのY座標 .style("visibility","visible") // ツールチップを表示 .text("toolTipData:" + t ); // ツールチップの文字 }) .on("mouseout",function(){ toolTip.style("visibility","hidden"); // ツールチップを非表示 }) drawScale(); }); |
1 2 3 4 5 6 7 8 9 10 11 |
xData,yData,toolTipData 20,5,1 60,10,6 120,20,15 25,50,34 50,80,60 80,100,80 100,120,100 180,170,150 240,250,220 300,290,250 |
グラフの表示範囲をデータに合わせる
まずはサンプルコードを実行すると・・・
サンプルコードの実行結果はこちら
●HTMLファイルは、上部のサンプルプログラムと同一です。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
/* 散布図を表示する */ d3.csv("graphData.csv",function(error,data){ var svgEle = document.getElementById("graph"); var svgWidth = window.getComputedStyle(svgEle,null) .getPropertyValue("width"); var svgHeight = window.getComputedStyle(svgEle,null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); svgHeight = parseFloat( svgHeight ); var offsetX = 30; // X座標のずれ var offsetY = 20; // Y座標のずれ var xScale; var yScale; var xAxisW = svgWidth - 30; var yAxisH = svgHeight - 20; var svg = d3.select("#graph"); var arrData = []; data.forEach(function(d,i){ arrData.push([ d.xData * 1 , d.yData * 1, d.toolTipData * 1 ]); }); // 目盛りを表示 drawScale(); var circleElements = svg .selectAll("circle") // circle要素を追加 .data(arrData); circleElements .enter() .append("circle") // CSSクラスを指定 .attr("class","mark") .attr("cx", svgWidth / 2 + offsetX ) // X座標の目盛りを中央にする .attr("cy", svgHeight / 2 - offsetY ) // Y座標の目盛りを中央にする .attr("r",100) // 半径100の円 .attr("opacity",0) // 透明 .transition() // 設定後の座標までアニメーション .duration(2000) // アニメーションする時間 .ease("bounce") // バウンドする動きにする .attr("cx",function(d,i){ return xScale( d[0] ) + offsetX; // 1番目の要素をX表に指定 }) .attr("cy",function(d,i){ return yScale( d[1] ); // 2番目の要素をY座標に指定 }) .attr("r",4) // 点の半径 .attr("opacity", 1) function drawScale(){ var maxX = d3.max(arrData,function(d,i){ return d[0]; // X座標 }); var maxY = d3.max(arrData,function(d,i){ return d[1]; // Y座標 }); // 縦の目盛りを表示するために縮尺設定 yScale = d3.scale.linear() // 縮尺設定 .domain([ 0, maxY]) // 元データの範囲 .range([ yAxisH, 0]); // 実際の出力サイズ // 目盛りを表示 svg.append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - yAxisH - offsetY ) + ")" ) .call( d3.svg.axis() .scale(yScale) .orient("left") ); // 横の目盛りを表示するために縮尺設定 xScale = d3.scale.linear() // 縮尺設定 .domain([0, maxX]) // 元データの範囲 .range([0, xAxisW]); // 実際の出力サイズ // 目盛りを表示 svg.append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - offsetY ) + ")" ) .call( d3.svg.axis() .scale(xScale) .orient("bottom") ); // グリッドを表示 var grid = svg.append("g"); // 横方向と縦方向のグリッド間隔を自動生成 var rangeX = d3.range(50, maxX + 50, 50); var rangeY = d3.range(20, maxY, 20); // 縦方向のグリッドを作成 grid.selectAll("line.y") .data(rangeY) .enter() .append("line") .attr("class","grid") // (x1,y1) - (x2,y2) の座標値設定 .attr("x1", offsetX) .attr("y1", function(d,i){ return svgHeight - yScale(d) - offsetY; }) .attr("x2", xAxisW + offsetX) .attr("y2", function(d,i){ return svgHeight - yScale(d) - offsetY; }); // 横方向のグリッドを作成 grid.selectAll("line.x") .data(rangeX) .enter() .append("line") .attr("class","grid") // (x1,y1) - (x2,y2) の座標値設定 .attr("x1", function(d,i){ return xScale(d) + offsetX; }) .attr("y1", svgHeight - offsetY) .attr("x2", function(d,i){ return xScale(d) + offsetX; }) .attr("y2", svgHeight - offsetY - yAxisH); } // ツールチップを作成 var toolTip = d3.select("body") .append("div") .attr("class","tip"); // ツールチップを表示 circleElements .on("mouseover",function(d){ var x = parseInt( xScale( d[0] ) ); // 円のX座標 var y = parseInt( yScale( d[1] ) ); // 円のY座標 var t = parseInt(d[2]); // toolTipDataの値を格納する toolTip .style("left", offsetX + x + "px" ) // ツールチップのX座標 .style("top" , offsetY + 30 + y + "px") // ツールチップのY座標 .style("visibility","visible") // ツールチップを表示 .text("toolTipData:" + t ); // ツールチップの文字 }) .on("mouseout",function(){ toolTip.style("visibility","hidden"); // ツールチップを非表示 }) }); |
データの範囲に応じて表示するグラフをかえてみます。今までの書いてきた記事だと座標が1:1に対応してました。なので、データの値をそのまま座標として利用していきました。実際にグラフを表示するとなると、こんなに都合が良いデータはあまりありません。
そういうときに便利なのが、D3.jsのスケール(縮尺)です。元のデータの値が大きいとき、これまでのサンプルコードの実行結果をみると、グラフがはみ出しています。グラフ範囲に調整するには元のデータの0~