score:0

Your goal should be to use a setTimeout loop to repeatedly call a function that updates fruits (or exams) and then updates the view as outlined in the General Update Pattern. Something like

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)
});

I think you can figure out how to implement updateView() following the recommendation of General Update Pattern. The remaining challenge is how to prepare fruits.

First, the thing you're doing with the .forEach loops can be achieved using the .rollup() function of d3.nest. It's not mandatory, but it's cleaner. (Note that you have a bug with d.qty = + d.qty, which probably wants to become d.qty += d.qty).

Here's how it would look with .rollup() — assuming I didn't miss anything, since I haven't tried it in a console....

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

This will sum up all the quantities per fruit across ALL TIME. However, since you're looking to advance through time incrementally, you need to introduce some limits on how much should get summed per iteration of setTimeout. It's up to you how to define the limiting criteria, but here are a couple of ideas:

  // 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;
    });
  });

or

  // 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;
    });
  });

Using d3.sum implies that JavaScript is looping through all the data per iteration. There are other ways to set it up such that it's not looping through all that, since actually all that's needed is adding a new d.qty to a previously computed sum of older d.qty. But unless your dataset is humungous it's not a huge issue and probably not worth worrying about. And anyway, it's better to optimize AFTER you figure out how to do it the naive way. Hope that helps.


Related Query