[D3.js] Scale 함수 사용

D3.js/D3.js|2019. 11. 15. 09:00

[D3.js] Scale 함수 사용



지난시간에 이여 CSV 데이터 파일을 읽어 Circle 모양으로 시각화 코딩을 했었습니다. 단순히 좌표(X,Y) 데이터 값을 통해 캔버스 위치에 Circle을 그리는 명령만 내렸는데 이제 좀 더 디테일적으로 Circle의 Scale을 적용해 보는 시간을 갖도록 합시다. 이 내용은 예전에 v4 번전 때 살짝 기초만 공부할 때 정리했던 내용인데 v5로 다시 정리를 해보네요.

1. CSV 데이터 파일


지난시간에 읽은 CSV 데이터 파일을 circle 모양으로 시각화 코딩을 복습해 볼까요.

[data.csv] : 데이터 간격은 콤마(,) 입니다.(반지름 r를 추가)

x,y,r
50,50,1
100,150,3
150,50,5
200,150,7
250,50,9

2. Scale 함수 사용


[기존 소스]

<script src="https://d3js.org/d3.v5.min.js"></script>
<body>
  <script>
    //배경
    var svg = d3.select("body").append("svg")
          .attr("width",500)
          .attr("height",500)
          .style("background-color","yellow");
                    
    //데이터 출력
    function render(dataset){
      var circle = svg.selectAll("circle").data(dataset)
            .enter().append("circle")
             .attr("cx",function(d){return d.x;})
             .attr("cy",function(d){return d.y;})
             .attr("r",10)
             .attr("fill","red")
    }
        
    //데이터 읽기
    d3.csv("data.csv",type).then(function(data){      
         render(data);
    });
        
    //데이터 타입
    function type(d){
      d.x=+d.x;  //parseFloat(d.x);
      d.y=+d.y;  //parseFloat(d.y);
      return d;
    }
  </script>
</body> 

위 소스를 보면 attr()함수 내에 r이라는 속성이 있는데 이것이 바로 반지름입니다. 이 반지름 값은 지난시간까지 10으로 고정시켰는데 이제는 크기를 조절하여 시각화를 하고자 합니다.

d3.scaleLinear() 함수를 이용하여 크기를 자동으로 조절 하여 볼까요.

 d3.scaleLinear()
      .domain([참조최소값, 참조최대값])
      .range([출력최소값, 출력최대값]);

위 코딩은 기본 틀로 숙지해주시는 것이 좋습니다. 갑자기 아두이노 생각이 나네요. 아두이노에서 사용하는 map()함수와 유사하네요.

  • map(입력값,참조최소값,참조최대값,출력최소값,출력최대값)

사설은 접고 위 기본구조는 domain(참조범위)이고 range(반환범위)로 이해하시면 되겠습니다.

**예) **

var scale = d3.scaleLinear().domain([0, 10]).range([0, 100]);

위와 같이 지정하면,

scale(1) => 10이 반환.
scale(5) => 50이 반환
scale(10) => 100이 반환

그러면 실제 그렇게 나오는지 살펴 볼까요.

[소스]

<script src="https://d3js.org/d3.v5.min.js"></script>

<body>
 <script>
 
  var Scale = d3.scaleLinear().domain([0,10]).range([0,100]);

  console.log(Scale(1));
  console.log(Scale(5));
  console.log(Scale(10));

 </script>
</body>

[결과]


결과가 정상적으로 출력 되었습니다. 어떤 느낌인지 아시겠지요. 이 Scale 함수를 이용하여 Circle의 크기를 자동으로 조절하게 하면 데이터 시각화가 좀 더 그럴싸하게 표현 되겠죠.

3. 기존 소스에서 Scale함수를 적용하여 표현


    //데이터 출력
    function render(dataset){
      var circle = svg.selectAll("circle").data(dataset)
            .enter().append("circle")
             .attr("cx",function(d){return d.x;})
             .attr("cy",function(d){return d.y;})
             .attr("r",10)
             .attr("fill","red")
    }

기존 소스에서 수정할 부부는 위 데이터 출력 부분입니다. 경계를 나누어 코딩을 하니깐 어디를 수정해야 할지 쉽게 찾을 수 있게 되었죠.

수정 부분은 다음과 같습니다.

.attr("r",10) //반지름
.attr("fill","red") //원색

반지름 10이라고 기존에 고정했는데 Scale 함수를 이용하여 데이터 크기를 조절하겠습니다 그리고 고정 Red 색을 Color로 범위를 점해서 데이터 값에 따라서 Color를 지정해 봅시다.

위 Scale 기본구조에 맞게 한번 지정해 보았습니다.

var rScale = d3.scaleLinear()
                     .domain([0,10])
                     .range([0,50]);

데이터 참조범위는 0~10사이로 잡아놓고 반환 범위는 0~50사이로 해서 반지름의 크기를 조정했습니다. 데이터 값이 너무 클수도 있고 찾을 수도 있습니다. 그렇게 되면 캔버스 영역을 벗어나거나 너무 작게 Circle이 그려질 수 있기 때문에 캔버스의 영역에 맞게 데이터 전체의 Scale를 조절하기 위해서 위와 같이 코딩합니다.

다시, 3줄로 코딩을 나열하는게 좀 보기가 그러니깐 한줄로 표현해보죠. 추가로 Color도 동일하게 지정해 보겠습니다.

var rScale = d3.scaleLinear().domain([0,10]).range([0,50]);
var ColorScale = d3.scaleLinear().domain([0,10]).range(["red","blue"]);

이렇게 해서 Circle의 반지름과 Color를 만들어 놓았습니다. 이제는 참조 데이터 값에 맞게 반환 range()값만 가져와서 실제 캔버스에 그려주면 됩니다.

출력 데이터 값들을 순차적으로 Circle의 r, fill의 값을 지정하여 캔버스에 그리면 됩니다.

.attr("r",function(d){return rScale(d.r);})
.attr("fill",function(d){return ColorScale(d.r);});

종합해보면,
[소스]

<script src="https://d3js.org/d3.v5.min.js"></script>
<body>
  <script>
    var rScale = d3.scaleLinear().domain([0,10]).range([0,50]);
    var ColorScale = d3.scaleLinear().domain([0,10]).range(["red","blue"]);

    //배경
    var svg = d3.select("body").append("svg")
          .attr("width",500)
          .attr("height",500)
          .style("background-color","yellow");
                    
    //데이터 출력
    function render(dataset){
      var circle = svg.selectAll("circle").data(dataset)
            .enter().append("circle")
             .attr("cx",function(d){return d.x;})
             .attr("cy",function(d){return d.y;})
             .attr("r",function(d){return rScale(d.r);})
             .attr("fill",function(d){return ColorScale(d.r);});
    }
        
    //데이터 읽기
    d3.csv("data.csv",type).then(function(data){      
         render(data);
    });
        
    //데이터 타입
    function type(d){
      d.x=+d.x;  //parseFloat(d.x);
      d.y=+d.y;  //parseFloat(d.y);
      return d;
    }
  </script>
</body> 

[결과]


위 그림처럼 좀 더 그럴싸하게 데이터가 시각화 된 모습을 보실 수 있죠.

여기서, 여러분들은 먼가 아쉬운 점을 찾아야 합니다. 그 아쉬움은 뭘까요. 바로 domain()함수에 있습니다. 자세히 살펴보시면 참조 범위가 0~10사이로 고정되어 있습니다. 데이터를 시각화하는데 참조 데이터를 고정된 값의 범위로 묶어 둔다는 것은 좀 그렇죠. 만약 데이터가 20일 때는 프로그램 소스에 가셔서 직접 해당 위치의 값을 수정해야 합니다.

자연스럽게 참조값의 범위를 읽어 온 데이터 값에 따라 맞춰서 표현하고 싶을 때 그부분을 코딩에 담아 낸다면 좀 더 멋지겠죠.

다음은 그 부분에 대해 이야기 하겠습니다.

4. d3.max 함수로 참조 데이터 범위를 지정


D3.js 함수에는 min(), max()함수가 있습니다. 오늘 사용할 함수는 max()함수 입니다. 사용법은 동일하니깐 max() 사용법을 잘 보시고 나중에 최소값 사용할 일이 있으면 max 대신에 min으로 수정하세요.

그럼 d3.max( ) 함수를 사용해 볼까요.

var rScale = d3.scaleLinear().domain([0,10]).range([0,50]);

위 코딩이 있다면 domain([0,10])함수의 0~10사이의 참조범위를 지정할 때 이때 max값 10을 읽어 올 데이터의 최대값으로 지정해 봅시다.

예) 위의 data.csv 파일에 반지름은 r에 들어 있습니다. 그러면 다음과 같이 코딩하여 max값을 찾아 냅니다.

[소스]

<script src="https://d3js.org/d3.v5.min.js"></script>
<body>
  <script>

    //데이터 읽기
    d3.csv("data.csv",type).then(function(data){
      var max_r = d3.max(data, function(d) { return d.r; });
      console.log(max_r);
    });

    //데이터 타입
    function type(d){
      d.x=+d.x;  //parseFloat(d.x);
      d.y=+d.y;  //parseFloat(d.y);
      return d;
    }
  </script>
</body>     

[결과]


보시는 것과 같이 읽어 온 데이터 값 중의 최대값이 9가 나왔네요. 이렇게 해서 최대값을 캔버스의 나타낼 수 있는 최대값 범위가 되었네요.

최대값을 Scale 함수에 지정

 var rScale ;
 var max_r = d3.max(data, function(d) { return d.r; });
 
 rScale = d3.scaleLinear().domain([0,max_r]).range([0,50]);

위 코딩은 대충 의미를 아시겠지요.

종합해보면,

[소스]

<script src="https://d3js.org/d3.v5.min.js"></script>

<body>
 <script>

   var rScale ;
   var ColorScale ;
   var svg = d3.select("body").append("svg")
         .attr("width",500)
         .attr("height",500)
         .style("background-color","yellow");

   function render(dataset){
     var circle = svg.selectAll("circle").data(dataset)
           .enter().append("circle")
            .attr("cx",function(d){return d.x;})
            .attr("cy",function(d){return d.y;})
            .attr("r",function(d){return rScale(d.r);})
            .attr("fill",function(d){return ColorScale(d.r);});
   }

   d3.csv("data.csv",type).then(function(data){
        var max_r = d3.max(data, function(d) { return d.r; });
        rScale = d3.scaleLinear().domain([0,max_r]).range([0,50]);
        ColorScale = d3.scaleLinear().domain([0,max_r]).range(["red","blue"]);
        render(data);
   });

   function type(d){
     d.x=+d.x;  //parseFloat(d.x);
     d.y=+d.y;  //parseFloat(d.y);
     return d;
   }
 </script>
</body>

[결과]


아래와 같이 결과를 얻었습니다. 그런데 별 차이가 없어 보일 꺼에요. 그 이유는 기존 data.csv 파일을 사용했기 때문입니다.


마무리


CSV 데이터 파일을 시각화 할때 Scale 함수를 사용하는 방법을 살펴 보았습니다. 하다보니 꽤 내용이 길어졌는데 간단히 정리하면 딱 두줄 입니다.

var rScale = d3.scaleLinear().domain([0,10]).range([0,50]);
var ColorScale = d3.scaleLinear().domain([0,10]).range(["red","blue"]);

이걸 배우기 위해서 내용을 정리가 좀 안되고 길게 쓰게 되었네요. 한번 간단히 읽어보는 기분으로 보시고 방금 이야기한 이 두줄의 의미만 정확히 이해하시면 됩니다.

[출력]

  • rScale(데이터)
  • ColorScale(데이터)

이렇게 해서 D3.js를 이용하여 캔버스 크기에 맞게 자동으로 크기를 조절할 수 있게 되었습니다.

'D3.js > D3.js' 카테고리의 다른 글

[D3.js] scaleLinear 함수  (0) 2019.11.19
[D3.js] 데이터 배열 다룰 때 유용함 함수  (0) 2019.11.18
[D3.js] 코딩의 가독성 높이기  (0) 2019.11.14
[D3.js] CSV, TSV, JSON, XML 시각화  (0) 2019.11.13
[D3.js] XML 파일 읽는법  (0) 2019.11.11

댓글()