如何汇总D3中.csv的过滤数据?

时间:2019-07-02 03:02:36

标签: csv d3.js

在此.csv文件中:

country,year,sex,num
Argentina,1985,male,150
Argentina,1985,female,240
Argentina,1986,male,100
Argentina,1986,female,200
Brazil,1985,male,10
Brazil,1985,female,140
Brazil,1986,male,45
Brazil,1986,female,48

我如何用d3.js对num列的值(150和240)求和,过滤国家/地区:阿根廷和年份:1985?

2 个答案:

答案 0 :(得分:0)

您可以使用D3的内置CSV函数将CSV读取到程序中,然后运行reduce以对其值求和。 CSV功能的使用方式在某种程度上取决于您使用的D3版本,但对于v5,它将是this D3 sub-library。求和的代码应如下所示:

// put the path to your csv file where I've written 'data.csv'
d3.csv('data.csv').then((data) => {
    const sum = data.reduce((acc, row) => {
        if(row.country === 'Argentina' && row.year === 1985) {
            acc += row.num;
        }
        return acc;
    })
})

您的总和将位于变量sum

答案 1 :(得分:0)

假设您希望在国家和年份相同的情况下求一个值的总和,而不仅仅是一次针对一个国家/一年:

您可以为此使用d3.nest(),这可以使您汇总行共享某些属性的列,在这种情况下,只要num和{ {1}}相同:

country

year
var nest = d3.nest()
    .key(function(row) { return row.country; })
    .key(function(row) { return row.year; })
    .rollup(function(values) { return d3.sum(values, function(d) {return +d.num; })  })
    .entries(data);
var csv = d3.select("pre").text();

var data = d3.csvParse(csv);

var nest = d3.nest()
    .key(function(row) { return row.country; })
    .key(function(row) { return row.year; })
    .rollup(function(values) { return d3.sum(values, function(d) {return +d.num; })  })
    .entries(data);
    
console.log(nest);

我正在将CSV解析为文本,因为我无法在代码段中加载实际的CSV。

下面说明了代码,并演示了一种替代结构,其中输出是d3.map()而不是数组。

按键分组数据

首先,我们可以按国家/地区对数据进行分组,为此,我们使用.as-console-wrapper { max-height: 100% !important; top: 0; }

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<pre>country,year,sex,num
Argentina,1985,male,150
Argentina,1985,female,240
Argentina,1986,male,100
Argentina,1986,female,200
Brazil,1985,male,10
Brazil,1985,female,140
Brazil,1986,male,45
Brazil,1986,female,48</pre>

提供一些数据后,嵌套的工作方式如下:

nest().key()
var nest = d3.nest()
    .key(function(row) { return row.country; })
var csv = d3.select("pre").text();

var data = d3.csvParse(csv);

var nest = d3.nest()
    .key(function(row) { return row.country; })
    .entries(data);
    
console.log(nest);

结果数组的每个唯一键值都有一个条目,在这种情况下,每个国家/地区只有一个条目:

.as-console-wrapper { max-height: 100% !important; top: 0; }

我们还可以通过创建第二个键来按年份分组:

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<pre>country,year,sex,num
Argentina,1985,male,150
Argentina,1985,female,240
Argentina,1986,male,100
Argentina,1986,female,200
Brazil,1985,male,10
Brazil,1985,female,140
Brazil,1986,male,45
Brazil,1986,female,48</pre>

如果我们复制上面的代码片段,则会得到一个类似的数组,但又增加了一个级别:

[
  {
    "key": "Argentina",
    "values": [
      {
        "country": "Argentina",
        "year": "1985",
        "sex": "male",
        "num": "150"
      },
      {
        "country": "Argentina",
        "year": "1985",
        "sex": "female",
        "num": "240"
      }, ...

汇总分组值

我们还可以使用var nest = d3.nest() .key(function(row) { return row.country; }) .key(function(row) { return row.year; }) 在此嵌套数组的最低层中求和:

[
  {
    "key": "Argentina",
    "values": [
      {
        "key": "1985",
        "values": [
          {
            "country": "Argentina",
            "year": "1985",
            "sex": "male",
            "num": "150"
          },
          {
            "country": "Argentina",
            "year": "1985",
            "sex": "female",
            "num": "240"
          }
        ]
      },
      {
        "key": "1986",
        "values": [
          {
            "country": "Argentina",
            "year": "1986",
            "sex": "male",
            "num": "100"
          }, ...
nest.rollup()
var csv = d3.select("pre").text();

var data = d3.csvParse(csv);

var nest = d3.nest()
    .key(function(row) { return row.country; })
    .key(function(row) { return row.year; })
    .rollup(function(values) { return d3.sum(values, function(d) {return +d.num; })  })
    .entries(data);

console.log(nest);

尽管结构相同,但与上面给出的结果略有不同:

.as-console-wrapper { max-height: 100% !important; top: 0; }

地图结果,或者

如果您要查找单个值,上述结构并不总是理想的。我们可以使用<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <pre>country,year,sex,num Argentina,1985,male,150 Argentina,1985,female,240 Argentina,1986,male,100 Argentina,1986,female,200 Brazil,1985,male,10 Brazil,1985,female,140 Brazil,1986,male,45 Brazil,1986,female,48</pre>而不是[ { "key": "Argentina", "values": [ { "key": "1985", "value": 390 }, { "key": "1986", "value": 300 } ] } ... 来创建d3 map,以便我们可以轻松地访问任何一个值:

nest.map()

在这里起作用:

nest.entries()
var nest = d3.nest()
    .key(function(row) { return row.country; })
    .key(function(row) { return row.year; })
    .rollup(function(values) { return d3.sum(values, function(d) {return +d.num; })  })
    .map(data);

console.log(nest.get("Argentina").get("1985"));
var csv = d3.select("pre").text();

var data = d3.csvParse(csv);

var nest = d3.nest()
    .key(function(row) { return row.country; })
    .key(function(row) { return row.year; })
    .rollup(function(values) { return d3.sum(values, function(d) {return +d.num; })  })
    .map(data);
    
console.log("Argentina, 1985: ",nest.get("Argentina").get("1985"));