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



我正在尝试在 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();

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

未捕获(承诺中)类型错误:data.filter 不是一个函数(...)

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

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

首先,没有办法使用d3.csv加载/解析 CSV 的前n行,恐怕这是不可能的。不幸的是,您必须加载/解析所有文件,如果文件很大,这可能会很不方便,这意味着用户必须等待整个文件加载/解析才能绘制图表。另外,值得一提的是,由于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>

Gerardo Furtado的答案要补充一件事:你的例子是这样的结构:

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

d3.csvV5 中,如果一个函数在这里作为这样的参数传递,则每行调用一次传递一个表示该行的对象、其索引和列键数组,从而允许更改行。因此,具体错误是因为此回调中的第一个 arg 是表示行的对象,而不是表示数据集的数组。

然后,当它们全部完成时,承诺完成,并触发提供.then(someFunction)的回调。

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

transformRow函数是可选的;如果提供了一个函数,则它为每行返回的任何内容都将替换数据中的该行。

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

所以例如:

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)
}
<script src="https://d3js.org/d3.v5.min.js"></script>

最新更新