简体   繁体   English

D3:如何在标准化堆积条形图上进行更新模式?

[英]D3: How to do an update pattern on normalized stacked bar chart?

I got my normalized stacked bar chart working, but I'm trying to add an update function & I'm having trouble getting it to work.我的标准化堆积条形图可以正常工作,但我正在尝试添加更新功能,但无法正常工作。 Basically, I'm trying to add another column to my CSV file to help sort the data and it's messing with the graph.基本上,我正在尝试向我的 CSV 文件中添加另一列以帮助对数据进行排序,但它会弄乱图表。 Here's what I have so far:这是我到目前为止所拥有的:

var aUtils = (function () {
  function init(options) { 
  var defaults = {};
  options = $.extend(defaults, options);

var margin = {top: 20, right: 20, bottom: 30, left: 40};

var containerWidth = $('.graph__container').width(),
    containerHeight = $('.graph__container').height(),
    width = containerWidth,
    height = containerHeight;

var svg = d3.select(".graph__container")
            .append('svg');
svg.attr({
   'width' : width,
  'height' : height
});

var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleBand()
          .rangeRound([0, width])
          .padding(0.1)
          .align(0.1);

var y = d3.scaleLinear()
          .rangeRound([height, 0]);

var z = d3.scaleOrdinal()
          .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b"]);

var stack = d3.stack()
              .offset(d3.stackOffsetExpand);

d3.csv("data.csv", type, function(error, data) {
  if (error) throw error;

  data.sort(function(a, b) { return b[data.columns[1]] / b.total - a[data.columns[1]] / a.total; });

  x.domain(data.map(function(d) { return d.etailer; }));
  z.domain(data.columns.slice(1));

  var layer = g.selectAll(".layer")
    .data(stack.keys(data.columns.slice(1))(data))
    .enter().append("g")
      .attr("class", "layer")
      .attr("fill", function(d) { return z(d.key); });

  layer.selectAll("rect")
    .data(function(d) { return d; })
    .enter().append("rect")
      .attr("x", function(d) { return x(d.data.etailer); })
      .attr("y", function(d) { return y(d[1]); })
      .attr("height", function(d) { return y(d[0]) - y(d[1]); })
      .attr("width", x.bandwidth());

  g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  g.append("g")
      .attr("class", "axis axis--y")
      .call(d3.axisLeft(y).ticks(10, "%"));

  var legend = layer.append("g")
      .attr("class", "legend")
      .attr("transform", function(d) { var d = d[d.length - 1]; return "translate(" + (x(d.data.etailer) + x.bandwidth()) + "," + ((y(d[0]) + y(d[1])) / 2) + ")"; });

  legend.append("line")
      .attr("x1", -6)
      .attr("x2", 6)
      .attr("stroke", "#000");

  legend.append("text")
      .attr("x", 9)
      .attr("dy", "0.35em")
      .attr("fill", "#000")
      .style("font", "10px sans-serif")
      .text(function(d) { return d.key; });

});

function type(d, i, columns) {
  for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
  d.total = t;
  return d;
}
}

return { 
  init : init 
}
})();

$(document).ready(function() { 
  aUtils.init(); 
});

My CSV file looks like this:我的 CSV 文件如下所示:

category etailer brandname1 brandname 2 brandname 3
air, amazon, 3, 4, 5
air, walmart, 1, 2, 3
air, target, 7, 8, 1
wind, target, 3, 4, 5
wind, walmart, 0, 9, 5
wind, amazon, 3, 5, 8

Right now I can get it working without the "category" column, but as soon as I add the category column so I can start working on the update pattern, the whole chart breaks.现在我可以在没有“类别”列的情况下让它工作,但是一旦我添加了类别列以便我可以开始处理更新模式,整个图表就会中断。 To clarify, I want "etailer" to be x axis, I want to display the different categories separately based on a click from a select list.澄清一下,我希望“etailer”是 x 轴,我想根据选择列表中的单击分别显示不同的类别。 I haven't been able to find any similar example online.我在网上找不到任何类似的例子。 Any direction would be much appreciated!任何方向将不胜感激!

I needed two main changes to fix this issue.我需要两个主要更改来解决这个问题。 The first is changing the type function to this:首先是将类型函数更改为:

    function type(d, i, columns) {
      for (i = 2, t = 0; i < columns.length; ++i) t += d[columns[i]] =  +d[columns[i]];
      d.total = t;
      return d;
    }

As you can see, I changed i = 1, to i = 2. Before I made this change, the function was trying to read the second column as a number.如您所见,我将 i = 1 更改为 i = 2。在进行此更改之前,该函数试图将第二列读取为数字。

My next change was to filter the data, using this function:我的下一个更改是使用此函数过滤数据:

       categoryData = data.filter( function(d) {
        return d.category === category;
       });

I can't totally explain what this does, it worked ¯_(ツ)_/¯我无法完全解释这是做什么的,它起作用了¯_(ツ)_/¯

I changed this line:我改变了这一行:

       var serie = g.selectAll(".serie")
      .data(stack.keys(data.columns.slice(2))(data))

To this:对此:

      var serie = g.selectAll(".serie")
      .data(stack.keys(data.columns.slice(2))(categoryData))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM