d3解析和绘制嵌套的csv数据

时间:2015-03-02 03:24:09

标签: csv d3.js

我是d3菜鸟尝试使用以下数据创建条形图:

date, fruit, qty
1/1/14, apple, 10
1/1/14, orange, 0
1/1/14, banana, 20
1/2/14, apple, 12
1/2/14, orange, 5
1/2/14, banana, 30    
1/3/14, apple, 16
1/3/14, orange, 15
1/3/14, banana, 40

在这个条形图中,每个水果都会有一个条形,它会以qty的高度增长,比如说,每天1秒(实时)(或csv的行) )。我没有尝试更新点击或任何其他互动。我希望这些酒吧自动增长。

我很容易使用静态数据渲染条形图,但我正在努力解析和循环数据。我引用了this example,但这有点过头了。

我试图使用以下代码解析csv:

    var fruits;

    d3.csv("faux_data.csv", function(error, data) {
        var parse = d3.time.format("%m-%d-%y").parse;

        exams = d3.nest()
                 .key(function(d) {return d.fruit; })
                 .entries(fruits = data);

        exams.forEach(function(s) {
            s.values
             .forEach(function(d) { d.date = parse (d.date); d.qty = + d.qty; } );
        });

    });

然后我不知道如何使用此代码更新我正在创建的rect svgs:

    var svgContainer = d3.select("body")
                        .append("svg")
                        .attr("width", 400)
                        .attr("height", 300);

    var rectangles = svgContainer.selectAll("rect")
                        .data(fruits)
                        .enter()
                        .append("rect");

    var rectangleAttributes = rectangles
                        .attr("x", function (d, i) { return (i * 55);})
                        .attr("y", function(d) { return (250 - d.qty);})
                        .attr("width", 50)
                        .attr("height", function(d) {return d.qty;});

有关d3和js如何处理csv数据的任何提示或明确解释(针对noob级别)将非常感激。

1 个答案:

答案 0 :(得分:0)

您的目标应该是使用setTimeout循环重复调用更新fruits(或exams)的函数,然后按照常规更新模式中的说明更新视图。像

这样的东西
d3.csv("faux_data.csv", function(error, data) {
  setTimeout(function() {
    fruits = ... // re-nest all the data
    updateView() // render view based on the current values of fruits
  }, 500)
});

我认为您可以按照常规更新模式的建议了解如何实施updateView()。剩下的挑战是如何准备fruits

首先,使用.forEach .rollup()函数可以实现d3.nest循环所做的事情。这不是强制性的,但它更清洁。 (请注意,您有d.qty = + d.qty的错误,可能想要成为d.qty += d.qty。)

以下是.rollup()的外观 - 假设我没有错过任何内容,因为我没有在控制台中尝试过它......

fruits = d3.nest()
  .key(function(d) {return d.fruit; })
  .entries(fruits = data);
  .rollup(function(values) {
    return d3.sum(values, function(d) {
      return d.qty;
    });
  });

这将总结所有时间内每个水果的所有数量。但是,由于您希望逐步增加时间,因此需要对每次setTimeout次迭代求和的数量进行一些限制。由您决定如何定义限制标准,但这里有几个想法:

  // This sums up the first 5 elements of each fruit.
  // Instead of hard-coding the 5, you can set and
  // increment a variable at each iteration
  .rollup(function(values) {
    return d3.sum(values.slice(0, 5), function(d) {
      return d.qty;
    });
  });

  // This sums up per fruit all values PRIOR to Jan, 1st 2015.
  // Instead of hard-coding the date, you can set and increment
  // a Date variable at each iteration
  .rollup(function(values) {
    return d3.sum(values, function(d) {
      if(Number(d) < Number(new Date(2015, 0, 1)))
        return d.qty;
      else
        return 0;
    });
  });

使用d3.sum意味着JavaScript循环遍历每次迭代的所有数据。还有其他方法可以设置它,以便它不会遍历所有这些,因为实际上所需要的只是将新的d.qty添加到先前计算的较旧d.qty的总和中。但除非你的数据集很有意思,否则它不是一个大问题,可能不值得担心。无论如何,最好在你弄清楚如何以天真的方式进行优化之后进行优化。希望有所帮助。