使用D3 v5中的d3.csv动态加载数据

时间:2018-04-20 12:25:40

标签: javascript database csv d3.js

我正在尝试在d3.js中构建一个动态加载条形图,它将从后端部分加载数据。使用d3.csv()函数,有没有办法从初始绘制的数据中只读取第一个n行数,然后根据我的JS逻辑加载后续数据?

tl; dr 我想有选择地访问d3.csv()函数中的数据。

我正在尝试运行以下代码:

var margin = {
            top: 20,
            bottom: 30,
            left: 40,
            right: 30
        },
        width = 600 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var loadData = function() {
        d3.csv("test_data.csv", function(data) {
            console.log(data.filter(function(d, i) {
                return i < 2;
            }));

            console.log(data.filter(function(d, i) {
                return i < 3;
            }))
        })
    }

    loadData();

但是,我在控制台中收到错误:

  

未捕获(承诺)TypeError:data.filter不是函数(...)

这让我相信这个数据不是一个数组。是这种情况还是我在这里遇到其他问题?

另外,如何在d3.csv函数中访问列(csv文件内)? (例如,如果我的csv数据文件包含两个名为a和b的列。)

2 个答案:

答案 0 :(得分:4)

首先,无法仅使用n加载/解析CSV的第一行d3.csv,我担心这是不可能的。不幸的是,您将不得不加载/解析所有文件,如果文件很大,这可能会很不方便,这意味着用户必须等待整个文件在绘制图表之前加载/解析。此外,值得一提的是,由于d3.csv将加载所有文件,后续过滤器无关紧要:只需使用您想要的数据行,不要向浏览器添加更多不必要的任务,只需使用您想要的行绘制图表。

回到你的主要问题:

您的数据是一个数组。这里的问题只是你使用d3.csv就好像是XHR,这是D3 v4的情况......但是,在D3 v5中,d3.csv是一个承诺。

所以,必须是:

d3.csv(url).then(callback);

看一下下面的演示:

var csv = URL.createObjectURL(new Blob([
  `foo,bar,baz
12,43,21
45,54,21
87,13,17
98,69,17`
]));

d3.csv(csv).then(function(data) {
  console.log(data.filter(function(d, i) {
    return i < 2;
  }));
})
<script src="https://d3js.org/d3.v5.min.js"></script>

关于第二个问题,d3.csv公开名为columns的数组属性中的列:

var csv = URL.createObjectURL(new Blob([
  `foo,bar,baz
12,43,21
45,54,21
87,13,17
98,69,17`
]));

d3.csv(csv).then(function(data) {
  console.log("columns are: " + data.columns)
})
<script src="https://d3js.org/d3.v5.min.js"></script>

答案 1 :(得分:2)

要添加到Gerardo Furtado的答案中有一件事:您的示例结构如下:

d3.csv('some_file.csv', someFunction)

d3.csv V5中,如果函数在此处作为参数传递,则每个 会调用一次,传递 object 表示该行,其索引和列键数组,允许更改行。因此,特定错误是因为此回调中的第一个arg是表示行的对象,而不是表示数据集的数组。

然后,当他们全部完成后,承诺就完成了,并且.then(someFunction)提供了一个回调。

d3.csv('some_file.csv', transformRow).then(processData)

transformRow函数是可选的;如果提供了一个,那么每行返回的内容都会替换数据中的那一行。

然后processData回调获取一个行数组,其属性为columns,这是原始列名称的数组(因此如果transformRow返回一个具有不同属性键的对象,data.columns不匹配每行的属性。)

例如:

&#13;
&#13;
    var csv = URL.createObjectURL(new Blob([
     `name,start,end
      SOMETHING,123,321
      INVALID,321,123
      ANOTHER,111,333`
    ]));

    d3.csv(csv, processRow).then(processData)
    
    function processRow (row, index, columnKeys) {
      row[columnKeys[0]] = row[columnKeys[0]].trim().toLowerCase()
      row.duration = row.end - row.start // this new property doesn't change data.columns
      if (row.end > row.start) return row
    }
    
    function processData (data) {
      console.log(data, data.columns)
    }
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;