单水平堆叠条

时间:2018-04-19 09:17:54

标签: javascript d3.js

我尝试创建一个水平单个堆叠条,用作从零件到整个图形。有点像饼图,但是一个酒吧。我以前能够创建一个正常的垂直和堆积条形图,但我没有遇到同样的问题,而且根本没有显示矩形元素。

我删除了y轴,因为标签将通过图例或附加文字。

这是我得到的错误:

  

d3.min.js:2未捕获的TypeError:无法将undefined或null转换为   宾语       在切片()       在Function.n.range(d3.min.js:2)       在抽奖(singlestackedsharebar.html:94)       在d3.min.js:2       在对象。 (d3.min.js:2)       在k.call(d3.min.js:2)       在XMLHttpRequest.e(d3.min.js:2)

我认为当我创建堆栈和系列时会出现问题。当我记录该系列时,似乎下一个数组并没有像以前那样添加它们。

这里是完整的代码:

function draw(data) {

  // Turns all the strings in the csv into integer values.

  data.forEach(function(d) {
    d.Total = +d.Total;
  });

  var width = document.getElementById('barchart').offsetWidth,
    height = document.getElementById('barchart').offsetHeight;

  var margin = {
    top: 50,
    right: 200,
    bottom: 140,
    left: 260
  };

  var svg = d3.select('#barchart')
    .append('svg')
    .attr('width', '100%')
    .attr('height', '100%')
    .attr('viewBox', '0 0 ' + width + ' ' + height)
    .append('g');

  width = width - margin.left - margin.right,
    height = height - margin.top - margin.bottom;

  svg.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  // Create x and y scale.

  var xScale = d3.scaleLinear()
    .range([0, width]);

  var yScale = d3.scaleBand()
    .range([0, height])
    .padding(0.1);

  // Create domains.

  xScale.domain([0, d3.max(data, function(d) {
    return d.Total;
  })]);

  // Create axes.

  var x_axis = svg.append('g')
    .attr('class', 'axis')
    .attr('padding', 1)
    .attr('transform', 'translate(' + 0 + ',' + height + ')')
    .call(d3.axisBottom(xScale)
      .ticks(10, 's'));

  // Choose which columns to have as keys with slice method.

  var keys = data.map(function(d) {
    return d.Type;
  });

  // Create stack of the data with keys.

  var stack = d3.stack([data])
    .keys(["Total"]);

  console.log(keys);

  // Create series of the data.

  var series = stack(data);

  console.log(series);

  // Create color scale with colorbrewer or pass in array of colors.

  var colorScale = d3.scaleOrdinal()
    .domain([0, 12])
    .range(colorbrewer.Oranges[12]);

  // Append rectangles.

  var bars = svg.append('g')
    .selectAll('g')
    .data(series)
    .enter()
    .append('g')
    .attr('fill', function(d) {
      return colorScale(d.key);
    })
    .selectAll('rect')
    .data(function(d) {
      return data.d;
    })
    .enter()
    .append('rect')
    .attr('x', function(d, i) {
      return xScale(d[0]);
    })
    .attr('width', function(d, i) {
      return xScale(d[1]) - xScale(d[0]);
    });

};

<body>
d3.csv('https://raw.githubusercontent.com/dieterholger/dieterholger.github.io/master/data/disputeshare.csv', draw);
</body>

1 个答案:

答案 0 :(得分:2)

你这里有很多问题。首先是次要的:

  1. 矩形必须具有yheight属性;
  2. 您正在选择输入选择中的现有元素(而不是使用selectAll(null));
  3. 您的x比例使用最大总数作为最高域值。而不是那样,它应该是总和。
  4. 但到目前为止,这里最重要的问题是堆栈生成器。您根本无法将堆栈生成器与您拥有的数据一起使用,即......

    [
        {2015: "1528", 2016: "1187", Type: "Disputed Settlement Criteria/Bet Instructions", Total: 2715},
        {2015: "999", 2016: "676", Type: "Price Dispute", Total: 1675},
        {2015: "571", 2016: "299", Type: "Late Bets", Total: 870}
        //etc...
    ];
    

    ...用于创建单个栏。最重要的是,您的keys方法是错误的。

    您应该做的是在其上创建一个包含单个对象的数组

    var newData = [{}];
    
    data.forEach(function(d) {
        newData[0][d.Type] = d.Total
    });
    

    使用这个新数组的堆栈生成器。

    以下是使用您的代码作为基础并应用我提到的所有更改的演示。另外,我改变了演示的SVG的高度和宽度:

    function draw(data) {
    
      // Turns all the strings in the csv into integer values.
    
      data.forEach(function(d) {
        d.Total = +d.Total;
      });
    
      var width = 500,
        height = 100;
    
      var margin = {
        top: 10,
        right: 10,
        bottom: 30,
        left: 10
      };
    
      var svg = d3.select('body')
        .append('svg')
        .attr('width', '100%')
        .attr('height', '100%')
        .attr('viewBox', '0 0 ' + width + ' ' + height)
        .append('g');
    
      width = width - margin.left - margin.right,
        height = height - margin.top - margin.bottom;
    
      svg.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
    
      // Create x and y scale.
    
      var xScale = d3.scaleLinear()
        .range([0, width]);
    
      var yScale = d3.scaleBand()
        .range([0, height])
        .padding(0.1);
    
      // Create domains.
    
      xScale.domain([0, d3.sum(data, function(d) {
        return d.Total;
      })]);
    
      // Create axes.
    
      var x_axis = svg.append('g')
        .attr('class', 'axis')
        .attr('padding', 1)
        .attr('transform', 'translate(' + 0 + ',' + height + ')')
        .call(d3.axisBottom(xScale)
          .ticks(10, 's'));
    
      // Choose which columns to have as keys with slice method.
    
      var keys = data.map(function(d) {
        return d.Type;
      });
    
      var newData = [{}];
    
      data.forEach(function(d) {
        newData[0][d.Type] = d.Total
      });
    
      // Create stack of the data with keys.
    
      var stack = d3.stack()
        .keys(keys);
    
      // Create series of the data.
    
      var series = stack(newData);
    
    
      // Create color scale with colorbrewer or pass in array of colors.
    
      var colorScale = d3.scaleOrdinal()
        .domain([0, 12])
        .range(d3.schemeCategory10);
    
      // Append rectangles.
    
      var bars = svg.selectAll(null)
        .data(series)
        .enter()
        .append('g')
        .attr('fill', function(d) {
          return colorScale(d.key);
        })
        .selectAll('rect')
        .data(function(d) {
          return d;
        })
        .enter()
        .append('rect')
        .attr('x', function(d, i) {
          return xScale(d[0]);
        })
        .attr('width', function(d, i) {
          return xScale(d[1]) - xScale(d[0]);
        })
        .attr("height", yScale.bandwidth());
    
    };
    
    d3.csv('https://raw.githubusercontent.com/dieterholger/dieterholger.github.io/master/data/disputeshare.csv', draw);
    <script src="https://d3js.org/d3.v4.min.js"></script>