【问题标题】:How to put first row in tsv to row thead <th> in table and the rest go to tbody <td> with d3如何将 tsv 中的第一行放到 table 中的行 thead <th> 中,其余的到 tbody <td> 与 d3
【发布时间】:2014-02-13 14:42:32
【问题描述】:

我正在尝试通过创建表格来学习 D3。下面的代码是我到目前为止所拥有的。

假设我的 TSV 数据有 3 列,我只希望第一行(数据中的 3 个对象)=> 在我的标题部分 其余的(我数据的第 4 个对象)进入 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; });
 });

【问题讨论】:

  • 您可以对.data() 使用不同的参数,即data[0] 和data.slice(1)。

标签: javascript d3.js


【解决方案1】:

正如 Lars 在 cmets 中所说,仅获取标题部分中的标题行只是在数据连接中仅提供那么多数据的问题。

但是,您的嵌套数据联接相当混乱,表明您可能不了解您的数据在做什么,所以让我们分解一下:

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

如果数据连接是嵌套选择(前一个选择的每个元素中的元素选择),那么您可以将子选择的数据集定义为函数。在这种情况下,传递给函数的值是 parent 元素的数据,而预期的返回值是一个 array,表示该父元素的子元素的所有数据.

最简单的嵌套选择是当您的原始数据集只是一个数组数组时。那是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; });

在任一嵌套选择中,该函数从父项(表示行的数组)中获取数据并返回它,以便数据连接将该数组拆分为单独的元素,每个元素对应一个 &lt;th&gt; 或 @ 987654327@细胞。

为了比较,你的原始数据连接中的复杂代码:

  .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)) 的结果。该函数采用传入的整数(column)或它在数组中的索引(i,它将是相同的整数),使用它在行的键列表中找到相应的值,然后使用它键从行对象中找到对应的值。

同样,由于 Javascript 数组也只是对象,因此这是可行的——但它是一种非常迂回的方式来创建一个与 row 数组相同的数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 2020-12-14
    • 2017-11-01
    • 1970-01-01
    • 2011-04-30
    • 2016-02-17
    • 2010-12-22
    相关资源
    最近更新 更多