2013 Felton 히스토그램 - 변형 1

Nicholas Felton2013 Annual Report에는 두 가지 히스토그램 변형이 포함되어 있습니다. 이 게시물은 다음과 같은 첫 번째 변형을 만든 방법을 다룹니다.

2013 연례 보고서(Nicholas Felton)의 히스토그램(변형 1) 세부 정보

꽤 전형적인 히스토그램. 그러나 스타일링 측면이 가장 흥미로웠습니다.
  • 오른쪽 상단 모서리에 배율 인수가 있는 잘린 측정값 레이블
  • 전체 측정 시리즈를 단일 선으로 연결하는 기울어진 측정 전환선

  • 아래에서 이 두 가지를 모두 달성한 방법을 다룰 것입니다.

    잘린 측정값 레이블



    숫자를 표현하는 데 필요한 유효 자릿수를 결정하는 데 직접 사용할 수 있는 수학 함수가 있기 때문에 이것은 매우 간단했습니다: Math.log10 . log10 함수는 숫자의 밑이 10인 로그를 계산하며, 이 로그는 그 안의 자릿수를 계산하는 데 사용할 수 있습니다. 예를 들어,
    Math.log10(623) = 2.7944880466591697
    배율 인수는 Math.floor 에 대한 호출에서 지수로 (Math.pow 사용) 결과의 전체 부분을 사용하여 계산됩니다.

    // We know we're showing 12 months so divide into 24 intervals
    labelXOffset = (width - margins.left - margins.right) / 24;
    // Calculate the scale factor used to get the most-significant digit
    const yMin = d3.min(data, yAccessor);
    const scale = Math.pow(10, Math.floor(Math.log10(yMin)));
    const formatter = d3.format(".0f");
    
    


    최소값은 레이블이 10배(또는 그 이상)의 계수로 인해 불필요하게 "평평화"되지 않도록 하기 위해 사용되었으며 D3의 서식 지정 기능은 각 측정값의 소수 부분을 폐기하는 데 사용되었습니다.

    SVG 내에서 측정 레이블은 text 요소를 사용하여 추가되었습니다.

    {#each data as datum}
      <text
        class="label"
        x={xScale(xAccessor(datum)) + labelXOffset}
        y={yScale(yAccessor(datum)) - labelYOffset}
        >{formatter(yAccessor(datum) / scale)}</text>
    {/each}
    


    추가 텍스트 요소를 사용하여 제목 및 축척 표시기가 추가되었습니다.

    <text class="title" x={margins.left} y={margins.top + textHeight}>
      TOTAL MONTHLY MEASUREMENT
    </text>
    <text
      class="scale-label"
      x={width - margins.right}
      y={margins.top + textHeight}>&times;{formatter(scale)}
    </text>
    


    전환 측정



    이 시각화를 구축하는 동안 두 가지 별도의 선 스타일을 구현했습니다. 첫 번째는 내장된 D3 라인 생성 도구를 사용했고 두 번째는 맞춤형 라인 생성기를 사용했습니다.

    D3 곡선을 사용한 첫 번째 시도



    처음에는 line 함수를 사용하여 히스토그램의 측정값을 나타내는 세그먼트 선을 생성하려고 했습니다. 선의 점을 연결하는 방법을 지정하는 데 사용할 수 있는 curve 함수가 있으며 특히 curveStepAfter 이 작업을 수행하는 것처럼 보였습니다.

    💣 그러나 이것이 작동하려면 데이터에 하나의 추가 항목이 있는지 확인해야 했습니다. 그렇지 않으면 D3가 최종 플랫 값 세그먼트를 생성하지 않습니다. 나는 단순히 마지막 지점을 복사하고 날짜를 미래의 한 달로 설정했습니다.

    // Massage the data so that there are enough points to complete the path
    // Copy the final entry in the array
    const myClonedData = R.clone(data[11]);
    // Now set the date to one month after
    myClonedData.month = "2021-01-01";
    const myData = [...R.clone(data), myClonedData];
    
    // First attempt - using 'curveStepAfter'
    const yLine = d3
      .line()
      .x((d) => xScale(xAccessor(d)))
      .y((d) => yScale(yAccessor(d)))
      .curve(d3.curveStepAfter)(myData);
    


    결과는 다음과 같습니다.

    D3 선 및 curveStepAfter를 사용한 첫 번째 시도

    이것은 실제로 꽤 좋은 출발점이었고 시각화를 다시 방문할 시간이 있을 때까지 사용했습니다.

    사용자 정의 라인 생성기를 사용한 두 번째 시도



    첫 번째 시도를 다시 할 시간이 조금 더 생긴 후 원본에서 사용된 기울어진 세그먼트 커넥터를 구현하기로 결정했습니다.
    line 내장 xy 함수의 사용을 측정 값 사이의 간격을 고려한 사용자 지정 함수로 대체해야 했습니다. 내 목표는 전환에 사용하기 위해 시작과 끝에서 각 측정 라인의 5%를 할당하는 것이었습니다. 그 결과 측정 자체에 대한 수평선을 생성한 다음 해당 측정의 끝에서 다음 측정의 시작까지 선을 생성하여 각 선분을 그렸습니다. 이 논리는 다음 함수에 포함되어 있습니다.

    function generateFeltonLine(data, xScale, xAccessor, yScale, yAccessor) {
      // this is only correct because of 0-based arrays
      // and # segments = # points - 1
      const segments = data.length;
    
      // Calculate displayed segment width and connector width
      const segmentWidth =
        xScale(xAccessor(data[1])) - xScale(xAccessor(data[0]));
      const connectorWidth = segmentWidth * 0.05; // 5% on each side
    
      // start with the first point, as it (and the last point)
      // are special cases
      let result = [
        [ xScale(xAccessor(data[0])), yScale(yAccessor(data[0])) ]
      ];
    
      // now all of the interior points
      for (let i = 1; i < data.length - 1; i++) {
        result.push([
          xScale(xAccessor(data[i])) - connectorWidth,
          yScale(yAccessor(data[i - 1])),
        ]);
        result.push([
          xScale(xAccessor(data[i])) + connectorWidth,
          yScale(yAccessor(data[i])),
        ]);
      }
      // add the final point
      result.push([
        xScale(xAccessor(data[data.length - 1])),
        yScale(yAccessor(data[data.length - 1])),
      ]);
      return result;
    }
    


    완료되면 다음과 같이 측정선을 만들 수 있습니다.

    // Second attempt - Felton-style connectors
    const yLine = d3
      .line()(
        generateFeltonLine(myData, xScale, xAccessor, yScale, yAccessor)
      );
    


    (제 생각에는) 시각화의 최종 버전이 훨씬 개선되었습니다.

    최종 히스토그램 버전 - 변형 1

    이 게시물을 작성하는 데 사용한 코드는 available on GitHub 입니다.

    질문이나 의견이 있으시면 언제든지 저에게 연락해 주십시오.

    좋은 웹페이지 즐겨찾기