开发者问题收集

我是否错误地映射或嵌套了这些数据?

2013-04-15
4506

我正在寻找一些关于如何修复我的数据以条形图形式可视化的指针。我创建了一个随时间变化的数据的小倍数可视化。由于数据收集方式的性质,数据共享某些属性。例如,您可以在下面看到 .csv 的摘录,其中 groupdate 重复:

group,date,totals
acid,1641,8438
acid,1641,0
acid,1641,0
beef,1641,977.85
beef,1641,0
beef,1641,0
beef,1641,164
beef,1641,5.25
bird,1641,121
bird,1641,0
bird,1641,12
bird,1641,1558
bird,1641,729
bird,1641,1680
bird,1641,0
bird,1641,343
bird,1641,3
bird,1641,2092
bird,1641,0
bird,1641,0
bird,1641,107
bird,1641,2679
bird,1641,167
bird,1641,649
boar,1641,41
boar,1641,13
cheese,1641,13
cheese,1641,22
cheese,1641,1071
cheese,1641,17195

(您可以在此处查看 整个数据集 。)

我遇到的问题是,无论何时共享 date ,它都会将数据堆叠在一起,而不是对 totals 列求和。例如,请参阅:

条形图

我遇到的问题是将数据显示为单个条形图。(我遇到了第二个问题,即 y 轴无法正确缩放)。我尝试使用 nest 来解决年份问题(这适用于 groups ),但我似乎无法通过 date 解决它。

到目前为止,这是我的代码:

var margin = {top: 20, right: 30, bottom: 30, left: 50},
    width = 400 - margin.right - margin.left,
    height = 150 - margin.top - margin.bottom,
    parse = d3.time.format("%Y").parse;

// scales
var x = d3.time.scale().range([0, width]),
    y = d3.scale.linear().range([0, height]),
    yscaled = d3.scale.linear().range([height, 0]);

// load data
d3.csv("revised.csv", function(error, data) {

  // nest values by group
  var groups = d3.nest()
      .key(function(d) { return d.group; })
      .entries(data);

  // parse dates and numbers, assume values are sorted by date
  // compute the maximum totals per group
  groups.forEach(function(s) {
    s.values.forEach(function(d) { d.date = parse(d.date); d.totals = +d.totals; });
    s.maxtotals = d3.max(s.values, function(d) { return d.totals; });
  });

  // compute the minimum and maximum date across groups
  x.domain([
    d3.min(groups, function(s) { return s.values[0].date; }),
    d3.max(groups, function(s) { return s.values[s.values.length - 1].date; })
  ]);
  // y.domain([0, d3.max(data, function(d) { return d.totals; })]);

  // add an SVG element for each group
  var svg = d3.select("body").selectAll("g")
      .data(groups)
    .enter().append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom);

  var canvas_g = svg.append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .each(function(d) {
          var g = d3.select(this);
          g.append("g");
        // .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        y.domain([0, d3.max(d.values, function(r) { return r.totals; })]);
        yscaled.domain([0, d3.max(d.values, function(r) { return r.totals; })]);

      // Draw the charts.

        g.selectAll("rect.aevents")
          .data(d.values)
        .enter().append("rect")
          .attr("height", function(p) {return y(p.totals)})
          .attr("width", 5)
          .attr("x", function(p, q) {return x(p.date)})
          .attr("y", function(p) {return height - y(p.totals)})
          // .on("click", function(p) {console.log(p.date)})
          .attr("class", "bar");
      });

  // draw x axis
  canvas_g.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.svg.axis().scale(x).orient("bottom"));

  // draw y axis
  canvas_g.append("g")
      .attr("class", "y axis")
      .call(d3.svg.axis().scale(yscaled).orient("left"));

  // add a small label for the group name
  svg.append("text")
      .attr("x", width + 40)
      .attr("y", height + 15)
      .attr("text-anchor", "end")
      .text(function(d) { return d.key; });

});

是否有其他方法可以循环遍历数据?或者,我需要以某种方式重组数据吗?提前谢谢您!

1个回答

首先,您可以阅读 答案,如果您想了解有关 d3.nest() 的更多信息,它将对您有所帮助。

对于您的问题,一个好方法是首先使用 d3.nest() 嵌套元素,然后将组映射到所需的形式。 给出:

function formatData(inputData){ 
    var array = d3.nest()
        .key(function(d){return d.group})
        .key(function(d){return d.date})
        .entries(inputData)
        .map(function(d){
            var group = d.key
            var values = d.values.map(function(dd){
                var date = dd.key
                var total = 0
                dd.values.forEach(function(ddd){
                    total = total + ddd.totals        
                })
                return {date:date, totals:total}
            })
            return {'group':group, 'values':values}
        })
    obj = {}
    array.forEach(function(d){
        obj[d.group] = d.values
    })
    return obj
}

其中 inputData 是使用 d3.csv() 加载的数据。这样,您就可以充分利用 nest() 和 `map()``

如果您只想为牛肉绘制条形图,现在可以执行以下操作:

var beefData = formatData(myInput).beef

jsFiddle: http://jsfiddle.net/chrisJamesC/FJmMD/3/

Christopher Chiche
2013-04-16