如何用组和汇总替换d3js嵌套函数

问题描述

我正在努力将一些较旧的d3js代码转换为最新版本(V6)。似乎旧功能nest()已被弃用。从现在开始,文档建议使用group()rollup(),但是它们并没有给出任何真正的好例子,并且我很难用这些新功能来实现相同的数据结构。

数据输入:

[
  {
    name: "Anton",year: "1990"
  },{
    name: "Anton",year: "1971"
  },{
    name: "Markus",year: "1981"
  },]

旧的D3代码

let nested = d3.nest()
  .key(function (d) { return d.name })     
  .key(function (d) { return d.year })
  .rollup(function (leaves) { return leaves.length })
  .entries(data)

输出(正确):

[
  {
    key: "Anton"
    values: [
      {
        key: "1990",value: 2
      }
      {
        key: "1971",value: 1
      }
    ]  
  },{
    key: "Markus"
    values: [
      key: "1981"
      value: 1
    ]
  }
]

代码

我试图以不同的方式组合grouprollup,但是我总是以另一个数据结构结束。我要结束的是这个:

let rollup = d3.rollups(data,v => v.length,d => d.name,d => d.year);
let arrayFromrollup = Array.from(rollup,([key,value]) => ({key,value}));

输出错误

[
  {
    key: "Anton"
    values: [
      ["1990",2],["1971",1]
    ]  
  },{
    key: "Markus"
    values: [
      ["1981",1]
    ]
  }
]

我会为您提供任何建议,显然,我发现的大多数类似问题/帖子都已经很老了,可以与nest一起使用。

解决方法

D3提供了出色的便利功能,但是随着ES6的兴起,数组和对象的操作变得更加容易。您可以使用纯ES6方法实现此目标:

const input = [{
    name: "Anton",year: "1990"
  },{
    name: "Anton",year: "1971"
  },{
    name: "Markus",year: "1981"
  },]

const expected = [
  {
    key: "Anton",values: [
      {
        key: "1990",value: 2
      },{
        key: "1971",value: 1
      }
    ],},{
    key: "Markus",values: [
      {
        key: "1981",value: 1,}
    ],];

// For ease of use,start with an object,we map key to values
// and unpack it later. The structure we go for now:
// { name: { year: count }}
const nameYearsCount = input.reduce((obj,{
  name,year
}) => {
  if (!(name in obj)) {
    obj[name] = {
      [year]: 1
    };
  } else {

    // I.e. if the year doesn't exist,default to zero
    obj[name][year] = (obj[name][year] || 0) + 1
  }
  return obj;
},{});

// Now transform it into the desired format
const result = Object.entries(nameYearsCount)
  .map(([name,yearsCount]) => {
    const values = Object.entries(yearsCount)
      .map(([year,count]) => ({
        key: year,value: count
      }));
    return {
      key: name,values
    };
  });

console.log(result);

,

这里有一些关于分组和汇总的很好的文档: https://observablehq.com/@d3/d3-group

在observable中将以下内容作为示例:

d3.rollup(athletes,v => {return {values: {len: v.length,earn:d3.sum(v,d => d.earnings)}}; },d => {return {key: d.nation}},d => {return {key: d.sport}}
     )