본문 바로가기

d3.js

bar chart

d3.js를 이용하여 기본적인 Bar Chart를 생성해보자.

Bar Chart 형태는 유명한 dc.js의 Sample 내의 Bar Chart를 생성 해보려고 한다.



필요한 데이터로는 x축은 날짜가 필요하며 y축은 수치 즉 numeric이 필요하다.

그래서 아래와 같은 샘플 데이터를 생성하였다.


 "date":"2013-02-18", "count":33, "price":3421000 },

{  "date":"2013-02-19", "count":4, "price":223000 },

{  "date":"2013-02-19", "count":6, "price":464000 },

{  "date":"2013-02-20", "count":2, "price":218000 },

{  "date":"2013-02-20", "count":4, "price":392000 },

{  "date":"2013-02-21", "count":8, "price":752700 },


위 데이터를 보면 date는 x축이 되겠고 count or price중 하나가 y축으로 지정하면 된다.

그런데 여기서 문제는 date가 unique하지 않다는 거다. 

Bar Chart의 x축은 date를 daily로 표현하므로 데이터를 date key로 하며 그룹으로(?) 묶어줘야 한다.

쉽게 설명하면 SQL문의 group by가 되겠다.


SELECT DATE, SUM(COUNT), SUM(PRICE) FROM TABLE GROUP BY DATE


이 점을 유념하고 Bar Chart를 생성해보자.


우선 Chart 영역 즉 사이즈를 지정한다.


var margin = {top: 10, right: 10, bottom: 40, left: 60},
    width =
960 - margin.left - margin.right,
    height =
110 - margin.top - margin.bottom;


x축은 date type이다 즉 날짜로 x축 scale을 지정해야 한다. d3.js는 날짜형 데이터로 scale을 지정할 수 있는 d3.time.scale() 을 지원한다. y축의 경우 숫자형이기 때문에 d3.scale.linear() 메소드를 사용하였다.

(만약 문자형이라면 d3.scale.ordinal()를 사용하여야 한다.)


var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);


이제 축을 생성한다.


var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(20);
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);


x축은 orient메소드를 이용하여 bottom으로 지정하였고 y축은 left로 지정하였다. ticks메소드는 축의 tick 갯수를 지정한다.


이제 기본설정은 끝이 났고 이전에 언급했던 데이터를 date로 group by해야 한다.

관련 코드는 아래와 같다. key는 date로 sum값은 count값으로 지정하였다.


var nodes = d3.nest()
.key(
function(d) { return d.date; })
   .rollup(
function(r){
         
return d3.sum(r, function(d){
              
return parseInt(d.count);
         })
    })
    .entries(data);


여기서 중요한 건 nodes 객체를 확인하는 것으로 console로 해당 객체를 확인해보면 아래 그림과 같다.

date는 key로 count는 values로 key값이 지정되어 nodes 객체가 생성된 것을 알 수 있다.



이제 데이터 가공도 끝이 났고 chart를 그려주기만 한다.


var svg = d3.select("body").append("svg")
   .attr(
"width", width + margin.left + margin.right)
   .attr(
"height", height + margin.top + margin.bottom)
   .append(
"g")
      .attr(
"transform", "translate(" + margin.left + "," + margin.top + ")");


x, y축의 scale영역의 정의역을 지정한다. d3.min, max 메소드로 key(날짜)의 범위를 지정한다.(scale과 domain?)


x.domain([
   d3.min(nodes,
function(d) { return new Date(d.key); }),
   d3.max(nodes,
function(d) { return new Date(d.key); })
]);
y.domain([
0, d3.max(nodes, function(d) { return d.values; })]);


x, y축을 생성한다. 


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

svg.append("g").attr("class", "y axis").call(yAxis);


각각의 데이터의 bar를 생성한다.


svg.selectAll(".bar").data(nodes).enter()
   .append(
"rect")
      .attr(
"class", "bar")
      .attr(
"fill", function(d) { return "steelblue"; })
      .attr(
"x", function(d) { return x(new Date(d.key)); })
      .attr(
"width", 2)
      .attr(
"y", function(d) { return y(d.values); })
     .attr(
"height", function(d) { return height - y(d.values) < 0 ? 0 : height - y(d.values); });


이제 저장 후 결과물을 확인해보면 아래와 같을 것이다.


그런데 x축의 tick text가 겹치는 것을 확인할 수 있다. 위 xAxis의 tick메소드의 값을 조절할 수도 있겠지만 아래와 같이

text를 회전을 시켜 보여주면 더 좋을 것 같다.


svg.selectAll(".x.axis text")
    .attr(
"transform", function(d) {
return "translate(" + this.getBBox().height * -2 + "," + this.getBBox().height + ")rotate(-45)";


소스보기



'd3.js' 카테고리의 다른 글

Google Maps + D3.js  (8) 2014.02.11
Using D3.js to draw a grid‎  (3) 2013.05.31
visualization using d3.js  (1) 2013.05.28