読者です 読者をやめる 読者になる 読者になる

fnwiyaBlog

EmacsとかLispとか可視化とか

D3.jsで散布図を書く

d3.jsでグラフを書くためのステップですが、
おおざっぱに

  1. datasetを用意する。(多次元配列やオブジェクトの配列の場合がおおい)
  2. コンテナの用意
  3. スケールの設定
  4. データをバインドする
  5. データ描画する
  6. 軸の設定

というように分解できます。

実際のコードは以下のようになります。

// 本来はcsvなどから読み込むと楽。数値は適当です。
var dataset=[
    {country:"AAA", votingRights:25, votedRights:18, aveAge:60.09}
    ,{country:"BBB", votingRights:22, votedRights:18, aveAge:45.51}
    ,{country:"CCC", votingRights:24, votedRights:23, aveAge:61.93}
    ,{country:"DDD", votingRights:17, votedRights:25, aveAge:52.95}
];

// 定数の宣言
var r = 3

// コンテナ
var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 600 - (margin.left + margin.right),
    height = 400 - (margin.top + margin.bottom);
var svg = d3.select('#foo') // 事前にHTMLに<svg id="foo"></svg>を作っておく
        .attr({
            width : width + (margin.left + margin.right),
            height : height + (margin.top + margin.bottom)
        })
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// スケール
var xScale = d3.scale.linear()
        .domain([15,35])
        .range([0,width]);
var yScale = d3.scale.linear()
        .domain([40,65])
        .range([height,0]);

// データバインド
svg.selectAll('circle')
    .data(dataset)
    .enter()
    .append('circle')
    .append('text');

// 描画
svg.selectAll('circle')
    .attr("id", function(d) {
        return d.country;
    })
    .attr({cx:0,r:1,fill:"gray"})
    .attr("cy", function(d){ return yScale(d.aveAge); });

svg.selectAll('circle')
    .transition()
    .duration(2000)
    .delay(function(d,i){ return xScale(d.votedRights); })
    .ease("circle-out")
    .attr({
        'cx' : function(d) {
            return xScale(d.votedRights);
        },
        'cy' : function(d) {
            return yScale(d.aveAge);
        },
        'r' : function(d) {
            return r;
        },
        'fill' : function(d) {
            return 'rgba(' + Math.floor(Math.random()*257) + ', ' +
                Math.floor(Math.random()*257) + ',' +
                Math.floor(Math.random()*257) + ', 0.6)';
        }
    });

// text
svg.selectAll("text")
    .attr({
        'x' : function(d) {
            return xScale(d.votedRights);
        },
        'y' : function(d) {
            return yScale(d.aveAge);
        }})
    .text(function(d) {
        return d.country;
    })
    .attr("font-family", "sans-serif")
    .attr("font-size", "11px")
    .attr("fill", "red");

// 軸を設定する。
var xAxis = d3.svg.axis()
        .scale(xScale)
        .orient("bottom")
        .tickSize(10, -height) // 棒の長さと方向。
        .tickFormat(function(d){ return d; });
var yAxis = d3.svg.axis()
        .ticks(5) // 軸のチックの数。
        .scale(yScale)
        .orient("left")
        .tickSize(5, -width);

svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("y", -10)
    .attr("x", 20)
    .style("text-anchor", "end")
    .text("平均年齢(歳)");

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);