[D3.js] Scale 함수 사용

in #kr-dev6 years ago

[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를 이용하여 캔버스 크기에 맞게 자동으로 크기를 조절할 수 있게 되었습니다.

Sort:  

코딩 공부하고있는데.... 먼가 엄청나네요 ,ㅎㅎ

그냥 기초적인 부분을 공부하면서 정리하고 있어요.
d3.js 사이트 가시면 진짜 엄청난 코딩을 보실 수 있을 꺼에요. ^^

코딩의 세계는 넓고도 다양한 것 같습니다.

코딩을 통해 많은 것들을 표현 할 수 있어 재미있는 것 같아요.
배워야 할 코딩도 많고 코딩의 바다에 한번 빠져 들면 그 매력에 헤어날 수 가 없는 것 같아요.

코딩에 취미를 가지신 분은 처음 봅니다. ㅋㅋ

스트레스가 쌓이면 전 코딩을 합니다.
코딩 관련 글들을 읽거나 네어버 카페같은 곳에서 코딩 질문 같은 것에 대한 해답을 찾는 등 뭔가를 상상하고 거기서 답을 찾는게 즐겁습니다.

타고난 엔지니어십니다. 한국의 빌게이츠가 나와야 되는데...

초딩교과목에 코딩이 의무화 되었나요??? 나이가 5학년대라 그런지 집중이 잘 안 되네요.

내년부터서인지 내년 되어봐야 할 듯요.
방가 후 수업으로는 현재 진행 중이죠.
중요한것은 초등학생 1~2학년생들도 기본 스크래치 or 엔트리를 조금만 가르치면 어느정도 하고 있고요. 창의과학인가 그걸로 아이들 배우는 것은 같더군요.

4차산업을 이끌 훌륭한 코딩기술을 가진것에 존경을 표합니다.

실전에 써먹어야지 좋은데 그냥 놀이로 즐기는 수준이라 아쉽네요.

<스팀잇으로 돈벌기>카페
출석이벤트 보팅입니다.
카페 활동 항상 감사드려요^^

감사합니다. ^^

Coin Marketplace

STEEM 0.18
TRX 0.15
JST 0.030
BTC 59025.51
ETH 2591.97
USDT 1.00
SBD 2.47