D3.js-JSON의 누적 막대 차트?

Aug 19 2020

이 바이올린을 다시 만들려고 노력했습니다. https://jsfiddle.net/1c5eqrp3/3/

내 데이터를 사용하여 구축중인 수평 누적 막대 차트의 맥락에서.

var bar1Data = [{
    position: 1,
    label: '70k',
    value: 1708026
  },
  {
    position: 2,
    label: '71K - 149K',
    value: 1915059
  },
];

//sort bars based on value
bar1Data = bar1Data.sort(function(a, b) {
  return d3.ascending(a.position, b.position);
})

var colors = ['green', 'blue'];

var bars = d3.select('#bars')
  .append('svg')
  .attr('width', 800)
  .attr('height', 200);

bars.selectAll('rect')
  .data(bar1Data)
  .enter()
  .append('rect')
  .attr('width', function(d) {
    return d;
  })
  .attr('x', function(d, i) {
    return sum(bar1Data.value, 0, i);
  })
  .attr('fill', function(d, i) {
    return colors[i];
  })
  .attr('y', 0)
  .attr('height', 100);

function sum(array, start, end) {
  var total = 0;
  for (var i = start; i < end; i++) total += array[i];
  return total;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="bar"></div>

내가 만든 bar1Data를 읽을 때까지 모든 것이 잘 진행되었습니다.

이제 다음과 같은 오류가 발생합니다.

Error: <rect> attribute width: Expected length, "[object Object]".
(anonymous) @ d3.js:1211
selection_each @ d3.js:1176
selection_attr @ d3.js:1233
(anonymous) @ bars3.js:23
Promise.then (async)
(anonymous) @ bars3.js:1
bars3.js:33 Uncaught (in promise) TypeError: Cannot read property '0' of undefined
    at sum (bars3.js:33)
    at SVGRectElement.<anonymous> (bars3.js:26)
    at SVGRectElement.<anonymous> (d3.js:1209)
    at Selection.selection_each [as each] (d3.js:1176)
    at Selection.selection_attr [as attr] (d3.js:1233)
    at bars3.js:25

d3.v5를 사용하여 누적 가로 막대 차트를 만드는 데 크게 어려움을 겪었습니다. d3.v4를 사용하여 다양한 예제를 시도했지만 제대로 작동하지 못했습니다. 이것은 내가 찾은 가장 간단하고 가벼운 예였습니다. 하지만 아직 비늘은 포함되어 있지 않습니다 (조금 후에 입력하겠습니다).

이 문제를 설명과 함께 해결하도록 도와 주시겠습니까?

답변

1 RubenHelsloot Aug 19 2020 at 12:48

에서는 .attr('width', function(d){ return d;})막대의 너비를 전체 개체로 설정합니다 d. 의 .data(bar1Data)값당 하나의 항목 이 생성 bar1Data되고 해당 값이 d모든 함수 에서처럼 액세스 가능하다는 것을 이해해야합니다 . 즉, 통과하자마자 .data(bar1Data)더 이상 해당 개체를 직접 만지지 않아야합니다.

이제 귀하의 데이터에서 이전의 모든 항목 값을 사용하여 해당 지점까지의 누적 합계를 계산하려는 것으로 이해하는 것 같습니다. 나는 대답에서 그것을 구현할 것이지만 stack = d3.stack(), 당신을 위해 그것을하는으로 당신을 지적하고 싶습니다.

값이 너무 큽니다. 도메인을 사용하여 변환해야합니다. 그렇지 않으면 달러당 1 픽셀 (또는 다른 화폐 단위)을 얻습니다. 즉, 막대가 모니터 너비의 100 배 오른쪽에 그려집니다.

var bar1Data = [{
    position: 1,
    label: '70k',
    value: 50
  },
  {
    position: 2,
    label: '71K - 149K',
    value: 40
  },
];

//sort bars based on value
bar1Data = bar1Data.sort(function(a, b) {
  return d3.ascending(a.position, b.position);
})

var colors = ['green', 'blue'];

var bars = d3.select('#bars')
  .append('svg')
  .attr('width', 800)
  .attr('height', 200);

bars.selectAll('rect')
  .data(bar1Data)
  .enter()
  .append('rect')
  .attr('width', function(d) {
    return d.value;
  })
  .attr('x', function(d, i) {
    // Note that I use `.map` here to take only the `.value` attribute
    // from the data and create an array of numbers.
    return sum(bar1Data.map((e) => e.value), 0, i);
  })
  .attr('fill', function(d, i) {
    return colors[i];
  })
  .attr('y', 0)
  .attr('height', 100);

function sum(array, start, end) {
  var total = 0;
  for (var i = start; i < end; i++) total += array[i];
  return total;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id='bars'>
</div>