Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can d3's key function handle a list element?

I have a CSV of fan fictions published over a time period. It looks something like:

id,published_date,characters
1,2017-01-01,'['Joe','Bob','Mary']'
2,2017-01-02,'['Mary']'
3,2017-01-02,'['Bob','Mary']'

I had pretty good success writing a key function by published_date, but now I want to see if I can write a key function for characters. So for the first row, Joe, Bob, and Mary would all be keys that have the value 2017-01-01, then in the second row 2017-01-02 would be added to Mary's key. At the end I would like to do a rollup on published_date in order to get a count of number of fan fictions published about Mary on each date. I think the end data would look something like this:

{
 Bob: {2017-01-01: 1}, {2017-01-02: 1},
 Joe: {2017-01-01: 1},
 Mary: {2017-01-01: 1}, {2017-01-02: 2} 
}

So for published_date, my code looked like:

var dates = d3.nest()
              .key(function(d) { return parseDate(d.published_date); })
              .rollup(function(v) { return v.length; })
              .entries(csv_data);

And if my characters column were not a list, then I believe this would work:

var dates = d3.nest()
              .key(function(d) { return d.characters; }) // key by character
              .key(function(d) { return parseDate(d.published_date); })
              .rollup(function(v) { return v.length; })
              .entries(csv_data);

Is there a way I can change key(function(d) { return d.characters; }) to actually create multiple keys?

Thanks!

like image 713
joe Avatar asked Jul 25 '26 05:07

joe


1 Answers

Unstack the data and you’ve got the right answer.

var csv = `id,published_date,characters
  1,2017-01-01,"[Joe,Bob,Mary]"
  2,2017-01-02,"[Mary]"
  3,2017-01-02,"[Bob,Mary]"`;

var csvData = d3.csvParse(csv, function(r) {
  return {
    id: +r.id,
    publishedDate: new Date(r.published_date),
    characters: r.characters.slice(1,-1).split(",")
  };
});

var data = [];
csvData.forEach(function(r) {
  r.characters.forEach(function(c) {
    data.push({
      id: r.id,
      publishedDate: r.publishedDate,
      character: c
    });
  });
});

Now this should work the way you want it to.

var nested = d3.nest()
  .key(function(d) { return d.character; })
  .key(function(d) { return d.publishedDate; })
  .rollup(function(v) { return v.length })
  .entries(data);
like image 104
Noleli Avatar answered Jul 27 '26 18:07

Noleli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!