Javascript 如何将tsv中的第一行放到第四行<;th>;在表中,其余的转到tbody<;td>;用d3

Javascript 如何将tsv中的第一行放到第四行<;th>;在表中,其余的转到tbody<;td>;用d3,javascript,d3.js,Javascript,D3.js,我试图通过创建一个表来学习D3。下面的代码是我到目前为止的代码 假设我的TSV数据有3列,我只希望第一行(数据中的3个对象)=>位于我的thead部分 剩下的(我的数据的第四个对象)进入tbody部分 d3.text("test.tsv", function(text) { var data = d3.tsv.parseRows(text); var table = d3.select("body").append("table"), thead = table.app

我试图通过创建一个表来学习D3。下面的代码是我到目前为止的代码

假设我的TSV数据有3列,我只希望第一行(数据中的3个对象)=>位于我的thead部分 剩下的(我的数据的第四个对象)进入tbody部分

d3.text("test.tsv",  function(text) {
    var data = d3.tsv.parseRows(text);

var table = d3.select("body").append("table"), 
      thead = table.append("thead"),
      tbody = table.append("tbody");

 var hrows = thead.selectAll("tr")
      .data(data)
      .enter()
      .append("tr");



      var hcells = hrows.selectAll("th")
      .data(function(row) {
        return d3.range(Object.keys(row).length).map(function(column, i) {
          return row[Object.keys(row)[i]];
          });
        })
      .enter()
      .append("th")
      .text(function(d) { return d; });

// ============
      var rows = tbody.selectAll("tr")
      .data(data)
      .enter()
      .append("tr");


      var cells = rows.selectAll("td")
      .data(function(row) {
        return d3.range(Object.keys(row).length).map(function(column, i) {
          return row[Object.keys(row)[i]];
          });
        })
      .enter()
      .append("td")
      .text(function(d) { return d; });
 });

正如Lars在评论中所说的,仅获取header部分中的header行只是在数据联接中提供那么多数据的问题

但是,嵌套数据联接相当混乱,这表明您可能不了解数据在做什么,因此让我们对其进行分解:

每当您执行d3数据连接(
d3.selectAll(“something”).data(dataset)
)时,数据集必须是一个数组,并且数组的每个元素都被分配给不同的DOM元素。数组的内容可以是单个值、复杂对象或子数组;无论哪种方式,他们都会被分配

如果数据联接是嵌套的选择(上一个选择的每个元素中的元素选择),则可以将子选择的数据集定义为函数。在这种情况下,传递给函数的值是父元素的数据,预期的返回值是表示该父元素的子元素的所有数据的数组

最简单的嵌套选择是当原始数据集只是一个数组数组时。这是由
d3.tsv.parseRows(text)
创建的数据结构:文件中的每一行都转换为字符串数组,文件中的所有行都收集到顶级数组中

这与
d3.tsv.parse(text)
d3.tsv(filename,function)
返回的结构不同,后者都将第一行作为列名读取,不将该行包含在数据中,并根据列名将所有其他行作为具有命名属性的对象返回。嵌套选择数据联接中使用的函数设计用于命名对象。它仍然可以工作,因为数组的键只是它的数字索引,但这是很多不必要的工作

var hrows = thead.selectAll("tr")
      .data(data[0]) //the first row of the data file
      .enter()
      .append("tr");

var hcells = hrows.selectAll("th")
      .data(function(row) { return row; }) //row is already an array
      .enter()
      .append("th")
      .text(function(d) { return d; });


var rows = tbody.selectAll("tr")
      .data(data.slice(1)) //a slice of the data array, starting from index 1
      .enter()
      .append("tr");

var cells = hrows.selectAll("td")
      .data(function(row) { return row; })
      .enter()
      .append("td")
      .text(function(d) { return d; });
在任何一种嵌套选择中,函数都会从父级(表示行的数组)获取数据并返回它,这样数据联接将把该数组拆分为它的单个元素,每个
单元格对应一个元素

为了进行比较,原始数据中的复杂代码将:

  .data(function(row) {
    return d3.range(Object.keys(row).length).map(function(column, i) {
      return row[Object.keys(row)[i]];
      });
假设行是一个对象,找出其中有多少个键(
object.keys(row).length
),创建一个从零到比该数字小一的整数数组(
d3.range(number)
),然后创建一个新数组,其中每个元素都是将该整数数组中的值传递给函数的结果(
array.map(function)
)。该函数获取传入的整数(
)或其在数组中的索引(
i
,这将是相同的整数),使用它在行的键列表中查找相应的值,然后使用该键从行对象中查找相应的值


同样,由于Javascript数组也只是对象,这是可行的——但创建与
行相同的数组是一种非常迂回的方法。

正如Lars在评论中所说的,在header部分仅获取header行只需在数据联接中提供那么多数据即可

但是,嵌套数据联接相当混乱,这表明您可能不了解数据在做什么,因此让我们对其进行分解:

每当您执行d3数据联接(
d3.selectAll(“something”).data(dataset)
)时,数据集必须是一个数组,并且数组的每个元素都会被分配给不同的DOM元素。数组的内容可以是单值、复杂对象或子数组;它们会按任意方式进行分配

如果数据联接是嵌套选择(上一个选择的每个元素内的元素选择),则可以将子选择的数据集定义为函数。在这种情况下,传递给函数的值是父元素的数据,预期返回值是表示该父元素的子元素的所有数据的数组

最简单的嵌套选择是当原始数据集只是一个数组数组时。这是由
d3.tsv.parseRows(text)
创建的数据结构:文件中的每一行都转换为字符串数组,文件中的所有行都收集到顶级数组中

这与
d3.tsv.parse(text)
d3.tsv(文件名、函数)返回的结构不同
都将第一行作为列名读取,但不将该行包含在数据中,并将所有其他行作为基于列名的具有命名属性的对象返回。嵌套选择数据联接中使用的函数是为与命名对象一起使用而设计的。它仍然可以工作,因为数组的键只是它的一部分数字指数,但这是很多不必要的工作

var hrows = thead.selectAll("tr")
      .data(data[0]) //the first row of the data file
      .enter()
      .append("tr");

var hcells = hrows.selectAll("th")
      .data(function(row) { return row; }) //row is already an array
      .enter()
      .append("th")
      .text(function(d) { return d; });


var rows = tbody.selectAll("tr")
      .data(data.slice(1)) //a slice of the data array, starting from index 1
      .enter()
      .append("tr");

var cells = hrows.selectAll("td")
      .data(function(row) { return row; })
      .enter()
      .append("td")
      .text(function(d) { return d; });
在任何一种嵌套选择中,函数都会从父级(表示行的数组)获取数据并返回它,这样数据联接将把该数组拆分为它的单个元素,每个
单元格对应一个元素

为了进行比较,原始数据中的复杂代码将:

  .data(function(row) {
    return d3.range(Object.keys(row).length).map(function(column, i) {
      return row[Object.keys(row)[i]];
      });
假设行是一个对象,找出其中有多少个键(
object.keys(row).length
),创建一个从零到比该数字小一的整数数组(
d3.range(number)
),然后创建一个新数组,其中每个元素都是将该整数数组中的值传递给函数的结果(
array.map(function)
)。该函数获取传入的整数(
)或其在数组中的索引(
i
),这将是