D3.js 基本4 – Scaleでデータを画面に収める

Share

データの数字がとても大きかったり最大値と最小値が全然違ったりする時、それを使って縦横の位置に設定すると画面の外に出てしまいます。すべてのデータを良い具合に画面全体に散らすためには、表示用にデータを変換する必要があります。
d3のscaleを使うと、簡単にデータの幅を画面表示用の幅に変換できます。これは線グラフなどグラフにはほぼ必ず使うと思います。
また、数だけではなく名目データに色を対応したい時など、いちいち設定するのが面倒なときは、このscaleの関数を使って自動的に色を割りふることもできます。

 

データの最大最小値をx、y、色の最大最小に合わせる:

まず結果とjavascript部分のコードです。

結果:
d3基本4-1scale_numeral

コード:

var width = 500;
var height = 200;

var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);

var gdp = [
					{年: 2007, gdp: 524, 増減: "up"},
					{年: 2008, gdp: 518, 増減: "down"},
					{年: 2009, gdp: 490, 増減: "down"},
					{年: 2010, gdp: 512, 増減: "up"},
					{年: 2011, gdp: 510, 増減: "down"},
					{年: 2012, gdp: 517, 増減: "up"},
					{年: 2013, gdp: 525, 増減: "up"}
					];

// スケール関数を作成。
var xScale = d3.scale.linear()
							.domain([2007,2013])
							.range([10,width+10]);

var yScale = d3.scale.linear()
							.domain([490,525])
							.range([height-10,10]);

var colorScale = d3.scale.linear()
    					.domain([490,525])
    					.range(["blue","red"]);

svg.selectAll("circle")
	.data(gdp)
	.enter()
	 .append("circle")
	 .attr("r",10)
	 // スケールを適用している。
	 .attr("fill", function(d){ return colorScale(d["gdp"]); })
	 .attr("cx", function(d){ return xScale(d["年"]); })
	 .attr("cy", function(d){ return yScale(d["gdp"]); });

解説:
結果を見ると、横の位置が年、縦の位置がGDPに対応していて、画面の中に全部収まっています。さらにgdpが一番低い時が青、高い時が赤で、間を中間色で徐々に変化させています。

データはgdpという名前で、年・gdp・前の年からの増減が入っています。前の年からの増減データは今は使っていません。

xScale、yScale、colorScaleがスケール関数を格納した変数です。
まずはxScaleを例にして、使い方を説明します。

var xScale = d3.scale.linear()
							.domain([2007,2013])
							.range([10,width+10]);

d3.scale~以下でスケール関数の設定を作っています。
・linear()は、スケール変換した後の最大値と最小値の間の縮尺を、一定の割合で変えるということです。powなら指数関数的に、logなら対数的に変わります。logは最大と最小の差が激しいデータによく使います。
・domainでデータ側の最大値と最小値を設定します。この場合は年の最大最小[2007,2013]を使っています。
・rangeで表示をする画面上の位置の最大最小を設定します。ここでは[10,width+10]と、svgのwidthの左端と右端を10だけ空けた範囲で表示するようにしています。

つまり、2007が10、2013がwidth+10に変換されて、その間の数は一定の割合で10とwidth+10の間に割り振られます。
もしdomainが[1900,2013]だった場合は、1900年から2013年をこの画面の範囲にマッピングするので、下の画像のようにほとんど右端に寄ってしまいます。
d3基本4-2scale_numeral_failure
だから、できるだけdomainもrangeも最大値と最小値を使うのがいいでしょう。

設定したスケールを使うには、変数xScale()で変換したいデータを囲みます。

.attr("cx", function(d){ return xScale(d["年"]); })

この場合はcxに使う値として年のそれぞれの数字を画面表示用の最大値と最小値の間の数に変換しています。

 

これが基本的な使い方ですが、yのスケールにはちょっとした便利なやり方があります。
画面の縦の位置yは、最上部が0で下に行くほど大きな数字になります。でもデータ側では普通、数字が大きいほうが上に行くようにしたいはずです。データの大きさに合わせて画面上の位置を高くするには、どちらかを逆方向に変換しないといけません。
yScaleのrangeを見ると、xの時と違って、大きい方のheightが左、小さい方が右に来ています。

var yScale = d3.scale.linear()
							.domain([490,525])
							.range([height-10,10]);

このようにrangeの最大と最小の部分を逆にすることで、簡単に逆方向に変換できます。

 

colorScaleでは、数ではなく色の最大最小値を設定して、中間を中間色で徐々に変えています。

var colorScale = d3.scale.linear()
    					.domain([490,525])
    					.range(["blue","red"]);

.range()の部分で、最小値の色=blue、最大値の色=redに設定しています。これを下のようにfillの部分で使えばデータの大きさに合わせて青と赤の間で色が変わります。

.attr("fill", function(d){ return colorScale(d["gdp"]); })

 

名目データの色を自動的に割り振る:

名目データにもスケール関数があります。その場合はd3.scale.ordinal~を使います。
でもここでは名目データに自動で色を割り当てる関数を使います。いろんな名目があるときに、いちいち全てに色を割り振るのが面倒なことが多いのでこれはとても便利です。
それにはd3.scale.category10やd3.scale.category20などを使います。10や20などは使う色の数です。

そのためには、1のコードのcolorScaleの代わりに下のスケールを設定します。

var colorCategoryScale = d3.scale.category10();

そしてfillの属性指定部分で、GDPデータのうち名目データである「増減」を使います。増減の名目は「up」か[down]かのどちらかで、GDPが前の年より上がったか下がったかという意味です。

.attr("fill", function(d){ return colorScale(d["増減"]); })

全体のコードはこうなります。

var width = 500;
var height = 200;

var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);

var gdp = [
					{年: 2007, gdp: 524, 増減: "up"},
					{年: 2008, gdp: 518, 増減: "down"},
					{年: 2009, gdp: 490, 増減: "down"},
					{年: 2010, gdp: 512, 増減: "up"},
					{年: 2011, gdp: 510, 増減: "down"},
					{年: 2012, gdp: 517, 増減: "up"},
					{年: 2013, gdp: 525, 増減: "up"}
					];

var xScale = d3.scale.linear()
							.domain([2007,2013])
							.range([10,width+10]);

var yScale = d3.scale.linear()
							.domain([490,525])
							.range([height-10,10]);

var colorScale = d3.scale.linear()
    					.domain([490,525])
    					.range(["blue","red"]);

// 量的なスケールの代わりに、category10()を使っている。
var colorCategoryScale = d3.scale.category10(); 

svg.selectAll("circle")
	.data(gdp)
	.enter()
	 .append("circle")
	 .attr("r",10)
	 // 増減という名目データを色に変換している。
	 .attr("fill", function(d){ return colorCategoryScale(d["増減"]); })
	 .attr("cx", function(d){ return xScale(d["年"]); })
	 .attr("cy", function(d){ return yScale(d["gdp"]); });

結果:
d3基本4-3scale_ordinal_color
解説:
増減という名目データのうち、upならオレンジ、downなら青に自動的に色がマッピングされました。

このd3.scaleは他にもたくさんの便利な関数があるので、よければ公式APIサイトのScalesの項目も見てみてください。

実際のHTMLファイルはリンク先に置いてあります:
1.データの最大最小値をx、y、色の最大最小に合わせる
2.名目データの色を自動的に割り振る

後記:
色スケールとアニメーションで花火を打ち上げてみました
d3_transition_wirework


コメントを残す