访问器(行)函数中的 d3.tsv/d3.csv 列

spy*_*dis 2 javascript csv d3.js

考虑以下 tsv 文件:

Code    k1  k2
pf_1    0.2 0.3
pf_2    0.3 0.7
pf_3    0.2 0.4
pf_4    0.1 0.6
pf_5    0.8 0.9
Run Code Online (Sandbox Code Playgroud)

我一直试图理解以下代码是如何工作的,但尚未找到明确的答案:

d3.tsv("test.tsv") 
    .row(function(d, i, columns){ d.total = columns.length; return d;})
    .get(function(d){ console.log(d);});
Run Code Online (Sandbox Code Playgroud)

我的具体问题如下:

  • 将第三个(列)参数映射到访问器(行)函数中的列名称的底层解析函数是什么?

  • 为什么访问器函数中需要行迭代器 (i) 参数?

Ger*_*ado 5

将第三个(列)参数映射到访问器(行)函数中的列名称的底层解析函数是什么?

访问器函数,也称为行转换函数,是为每行调用的函数,它需要 3 个参数(这将进一步回答你的第二个问题):

  • 第一个参数是
  • 第二个参数是索引,从零开始
  • 第三个参数是列名数组

第三个参数很有趣,它是在 D3 v4.x 中引入的。我相信它回答了你的第一个问题:

当您加载 CSV(或 TSV)时,d3.csv(或d3.tsv) 创建一个带有标题的数组属性columns,名为(请注意for...in循环等循环,因为它将包含该属性)。就您的示例而言,它是:

columns: ["Code", "k1", "k2"]
Run Code Online (Sandbox Code Playgroud)

这引出了你的第二个问题:

为什么访问器函数中需要行迭代器 (i) 参数?

你不知道。问题是,这段代码使用了第三个参数,即columns属性,为了能够使用第三个参数,我们必须提供它前面的两个参数,即使我们不使用它们:

.row(function(d, i, columns){ d.total = columns.length; return d;}) 
//3rd argument---------^
Run Code Online (Sandbox Code Playgroud)

JavaScript 中有一个约定,我认为不是很有名,即未使用的参数应命名为下划线 ( _)。在这种情况下,这个函数将是:

.row(function(d, _, columns){ d.total = columns.length; return d;}) 
//not used-------^
Run Code Online (Sandbox Code Playgroud)

因此,该代码的作用是获取 的值columns.length(即 3),并为每个对象创建一个新属性:

d.total = columns.length; return d;
Run Code Online (Sandbox Code Playgroud)

所以,对象最终会变成这样:

{Code: "pf_1", k1: "0.2", k2: "0.3", total: 3}
Run Code Online (Sandbox Code Playgroud)

有了新的财产total