[D3.js] 추가 Scale 함수

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

[D3.js] 추가 Scale 함수



Scale 관련 함수들을 정리하고 있습니다. 지난시간에 scaleLinear, scalePow, scaleLog 함수에 대해서 간단히 실험 하였고 오늘은 그외 다른 Scale 함수들을 몇개만 더 실험 해볼까 합니다. 과거 제 블로그에 정리하다가 만 내용인데 scaleThreshold(), scaleOrdinal(), scaleQuantize(), scaleQuantile() 함수에 대해서 다시 간단히 정리해 봅니다.

1. d3.scaleThreshold() 함수


  • 구조 : 임의의 수 x가 domain[1,10]의 범위를 가질 때 3가지 상황
    x < 1 일때 상황
    1 <= x < 10 일때 상황
    x >= 10 일때 상황

위와 같은 구조를 x가 값에 3가지 상황이 만들어 집니다.

쉽게 설명하자면,

예)

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

<body>
  <script>
    var data = [0,1,2,3,4,5,6,7,8,9,10,11];

        var a = d3.scaleThreshold().domain([1, 10])
                    .range(["red", "green", "blue"]);
                            
    data.forEach(function (d){console.log(a(d)); }); 

  </script>
</body>

[결과]


위 결과를 보는 것 같이 0은 red이고 1~9까지는 green이고 마지막으로 10은 blue가 됩니다. 대충 scaleThreshold()함수가 어떤식으로 동작하는지 아시겠지요.

추가로,

  var a = d3.scaleThreshold().domain([1, 10, 20])
                    .range(["red", "green", "blue","yellow"]);

위와 같은 상황이면 어떻게 동작할까요.


x < 1 일때 => red
1 <= x < 10 일때 => green
10 < x < 20 일때 => blue
x >= 20 일때 => yellow


위와 같은 형태가 됩니다.

2. d3.scaleOrdinal() 함수


이 함수는 도메인의 값은 범위를 나타낸다기 보다는 지정된 고정값을 나타내고 그 고정값에 대한 매칭되는 반환값을 내놓는 방식인데 실제 동작하는 과정을 통해 이해하셔야 이 말의 뜻을 알 수 있습니다. 그리고 이 함수를 제대로 이해하시면 scalePoint()나 scaleBand() 함수들이 있는데 비슷한 동작을 수행합니다. 하나의 함수를 제대로 이해하시면 이 두 함수를 쉽게 이해하실 수 있습니다.

var b = d3.scaleOrdinal().domain([0, 1])
                .range(["red", "green", "blue"]);

이렇게 선언되었다고 하죠. 여기서 0~1의 범위가 아니라 딱 0일때 1일때 두가진 상황만 존재한다는 것이죠. 포인터값이라고 해도 되겠죠.

0일때 => red
1일때 => green

출력되는 것이죠. 그럼 "blue"은 뭐냐고 할 수 있겠죠 구지 두가지 값만 존재하는 도메인인데 어디냐 쓰냐고 아리송 하겠죠.

domain([1,10]) 하면 1~10까지이겠지 하겠지만 여기서 1과 10 두가지 상황 밖에 존재하지 않습니다.

이때

    console.log(b.domain());  
    console.log(b(2));
    console.log(b.domain());  
    console.log(b(-1)); 
    console.log(b(3));
    console.log(b(5));
    console.log(b.domain());

찍어보시면 엄청 재밌는 상황이 발생합니다.

b.domain() => [0,1]  당연 나옵겁니다.
b(2) => blue
b.domain() => [0,1,2] 가 나옴

갑자기 도메인에 2가 추가되고 2가 "blue"되어 버렸죠.

b(-1) => red
b(3) => green
b(5) => blue
b.domain() => [0,1,2,-1,3,5] 가 나옴

보는것처럼, 현재 도메인에 포한된 포인터값이 없다면 새롭게 도메인에 추가됩니다. 여기서 추가 된 세번째 "blue"라는 반환값을 갖게 됩니다.

즉, 순차적으로 반환값이 반환되는데
domain[0, 1, 2, -1, 3, 5]

range 반환값이 red=>green =>blue=>red=>green=>blue... 이런식으로 반환을 하게 됩니다. 여기서 3가지 색은 순차적으로 도메인 등록된 값 순으로 색이 지정되는것이죠.

그리고,

  var c = d3.scaleOrdinal().domain(["a","b","c"])
                .range([0, 10]);

도메인[a,b,c]인데 반환[0,10]이네 하면서 분명히 scaleLinear()함수에서 domain과 range범위는 일치하라고 했는데 뭐지 하시는분들이 있을 수 있습니다. 방금전 scaleOrdinal()의 동작 원리를 이해하신 분이라면 "a"=0, "b"=10이니 "c"=0이 겠구나 하고 떠올라야 합니다.
각 포인터 값들에 대해서 range() 반환값들이 순차적으로 매칭되어서 반환된다는 점만 기억하세요

예)

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

<body>
  <script>
    var data = [0,1,2,3,4,5,6,7];

    var b = d3.scaleOrdinal().domain([0, 1])
                .range(["red", "green", "blue"]);;
                            
    data.forEach(function (d){console.log(b(d)); console.log(b.domain()); }); 

  </script>
</body>

[결과]
아래 결과에서 도메인 값이 추가 과정을 잘 보세요.


3. d3.scaleQuantize() 함수


domain()의 범위를 range()반환 값에 맞춰서 자동으로 domain() 범위를 쪼개서 분류합니다. 여러분들이 생각을 할 때 반환값을 기준으로 역으로 도메인의 범위를 지정해준다고 생각하시면 될 거에요.

식 : y = m round(x) + b

 var c = d3.scaleQuantize()
                 .domain([0, 30])
                 .range(["red", "green", "blue"]);

위와 같은 코딩을 하게 되면 어떻게 될까요.

도메인 범위가 다음과 같이 지정이 됩니다.

red   => 0~9
green=> 10~19
blue  =>21~29

즉, 도메인 범위 0~9면 red, 10~19면 green, 21~29면 blue가 자동으로 지정 된다고 생각하시면 이해하는데 편하 실 거에요.

저는 이 함수를 보면서 로또 6개의 구슬이 연상이 되더군요. 45까지의 숫자를 기준으로 이 함수를 사용하게 되면 6개의 색을 range() 범위를 지정하면 알아서 45개의 숫자가 나누어서 domain() 범위를 지정 할 수 있겠군 하고 상상하게 되더군요.

쉽게 설명하자면,

예)

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

<body>
  <script>
    var data = [0,1,2,3,4,5,6,7,8,9,10,11];

        var a = d3.scaleThreshold().domain([1, 10])
                    .range(["red", "green", "blue"]);
                            
    data.forEach(function (d){console.log(a(d)); }); 
        
    console.log(d.invertExtent("red"));
    console.log(d.invertExtent("green"));
    console.log(d.invertExtent("blue"));
  </script>
</body>

[결과]
아래 결과를 보시면 잘 쪼개져 있죠. 참고로 invertExtent()함수로 range()값에 해당되는 domain()값을 반환합니다. 어떻게 domain() 범위가 나뉘어 졌는지 확인 하실 수 있겠죠.


4. d3.scaleQuantile() 함수


scaleQuantize()와 유사한 동작을 수행 합니다. 이 함수는 그냥 간단히 예제로 살펴보도록 하죠.

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

<body>
  <script>
    var data = [0,1,2,3,4,5,6,7,8,9,10];

    var a = d3.scaleQuantile()
                     .domain([0, 10])
                     .range(["red", "green", "blue"]);                      
    data.forEach(function (d){console.log(a(d));}); 

    console.log(a.invertExtent("red"));
    console.log(a.invertExtent("green"));
    console.log(a.invertExtent("blue"));
  </script>
</body>

[결과]
scaleQuantize()와 같은 동일한 결과를 얻었습니다.


scaleQuantize()와 scaleQuantile() 차이점


scaleQuantile(), scaleQuantize() 이 두함수는 철자도 비슷하고 얼핏보면은 같은 함수라고 혼동할 정도로 참 닮았고 동작 또한 같아서 처음에 애먹은 함수입니다.

  d3.scaleQuantile().domain([0, 30, 50])
           .range(["red", "green", "blue"]);
 
  d3.scaleQuantize().domain([0, 30, 50])
          .range(["red", "green", "blue"]);

이렇게 주어졌을 때 결과를 보시면 다음과 같습니다.

예)

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

<body>
  <script>
    var data = [0,1,2,3,4,5,6,7,8,9,10];

    var a = d3.scaleQuantile().domain([0, 30, 50])
           .range(["red", "green", "blue"]);
 
    var b =  d3.scaleQuantize().domain([0, 30, 50])
          .range(["red", "green", "blue"]);;                        

    data.forEach(function (d){console.log(a(d));}); 
    console.log(a.invertExtent("red"));
    console.log(a.invertExtent("green"));
    console.log(a.invertExtent("blue"));

    data.forEach(function (d){console.log(b(d));}); 
    console.log(b.invertExtent("red"));
    console.log(b.invertExtent("green"));
    console.log(b.invertExtent("blue"));
  </script>
</body>

[결과]
invertExtent() 결과를 살펴보시면 확실히 차이점을 느끼 실 수 있을거에요.


즉, scaleQuanitle()함수는 0~30 범위를 고정해서 range()반환 갯수를 맞게 정의되지만, scaleQuantize()은 range() 반환 갯수에서 새롭게 추가된 50인 domain값에 맞게 재정의 된다는 차이점을 가지고 있습니다.

마무리


오늘 실험한 함수들은 scaleThreshold(), scaleOrdinal(), scaleQuantize(), scaleQuantile() 함수들에 대해 간단히 정리했습니다. 계속 관련 Scale함수들을 실험하면서 도대체 이 많은 함수들을 정확히 어떤 상황에 써야 할지 저도 좀 막막하긴 하네요. 나중에 예제들을 분석하면서 사용 방법을 터득해야 겠네요.

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

[D3.js] Color Scale 함수  (0) 2019.11.22
[D3.js] Color 함수  (0) 2019.11.21
[D3.js] scaleLinear 함수  (0) 2019.11.19
[D3.js] 데이터 배열 다룰 때 유용함 함수  (0) 2019.11.18
[D3.js] Scale 함수 사용  (0) 2019.11.15

댓글()