我在访问嵌套在 D3 中的数据时遇到问题。我相信我已经正确嵌套和汇总了数据,但随后我似乎无法访问我创建的新键/值对。
原始数据是一个 JSON blob,其中包含每个测试、完成日期、主题范围和分数。我想要实现的是在图表上按天为每个科目绘制一组单独的平均分数数据点。我之前使用过 Nest 来获得每日总体得分,并使用下面代码中引用的比例成功地绘制了此分数,但两级层次结构让我变得更好。当我记录新的“nestedData”对象时,它对我来说看起来是正确的(即预期值都在那里并按我的预期分组)。
我已经开发了几个不同的版本,但没有成功。我想知道我是否正在尝试做一些不是为 Nest 设计的事情,或者只是我的数组符号错误(很有可能!)。下面的代码显示了我正在使用的基本框架。我缺少的是一个过滤器来选择适当的主题以及从汇总中访问平均每日分数的正确方法。
// Takes original data and nest by date and then subject and rolls up on count of work and mean score
var dataToNest = data;
nestedData = d3.nest()
.key(function(el) {return el.dateCompleted})
.key(function(el) {return el.subject})
.rollup(function(leaves) {
return {"numberCompleted": leaves.length,
"averageScore": d3.mean(leaves, function(d) {return(d.score)})}
})
.entries(dataToNest);
// Format date as JS object
nestedData.forEach(function (el) {
el.key = new Date(el.key);
});
// Sort by date
nestedData.sort(function (a,b) {
return a.key - b.key;
});
// Code for scales etc not included
d3.select("svg")
.selectAll("circle")
.data(nestedData)
.filter(/* Filter by subject */)
.enter()
.append("circle")
.attr("class", "subject")
.attr("r", 5)
.attr("cy", function (d) {/* Get the average score for the selected subject */})
.attr("cx", function(d) {return xScale(d.key)});
我尝试过的一些事情:
对于过滤器,我尝试使用 d.values.key === 'Algebra' 的各种迭代来选择第二个键(主题键)的值
对于平均分数,我尝试使用 d.values.values.averageScore 的迭代以及迭代第二个数组的索引的函数来访问。
我强烈怀疑这是我对 javascript 中数组的结构和引用方式的理解有问题。我已经阅读了所有与此相关的帖子,但它们似乎主要是关于使用 Nest() 而不是从其中访问值。
更新
我的脚踏入大门如下:
svg.selectAll('.circle-group')
.data(nestedSubjectData)
.enter().append('g')
.attr('class', 'circle-group')
.attr('transform', function(d, i) {
return 'translate(' + xScale(d.key) + ',0)';
})
.selectAll('circle')
.data(function(d) {return d.values;})
.enter().append('circle')
.attr('class', function(d) {return d.key;})
.attr('cx', 0)
.attr('cy', function(d) { return d.values.averageScore; })
.attr('r', 5);
这会在第二级的每个数组中为averageScore 数据点添加一个圆圈,并应用一个可用于区分科目的类。
最佳答案
感谢 Lars 和一些相关问题,我终于弄清楚了。代码如下。在尝试了几种不同的方法后,我将嵌套顺序更改为更符合逻辑的顺序。由于日期和分数用于设置 x/y 坐标,因此更容易将它们保持在一个级别并将主题设置为第一级别。这样可以更轻松地拆分每个系列以进行样式设置和其他系列级交互(例如在可视化中打开或关闭整个主题)。
我的图表现在显示每个科目的每个每日平均分数的一个点,并在它们之间有一条线。您可以删除其中之一,它仍然可以正常工作。
我没有包含数据,但它是一个 JSON 文档。同样,我没有包含我的所有比例或 svg 创建。
// Nest data by subject and day and get average overall
var subjectDataToNest = data;
nestedSubjectData = d3.nest()
.key(function(el) {return el.subject}) // Nest by subject first
.key(function(el) {return el.dateAppeared}) // Within each subject array create an array for each day
.sortKeys(d3.ascending) // Sort the daily arrays by date (but this doesn't work reliably)
.rollup(function(leaves) {
return {
"averageScore" : d3.mean(leaves, function(d) {return(d.score)}) // Return the average score
}
})
.entries(subjectDataToNest);
// Draw circles for each subject and each
svg.selectAll('.subject-group')
.data(nestedSubjectData)
.enter().append('g')
// Create a group to contain each circle and (eventually) the path
.attr('class', 'subject-group')
.attr("id", function(d) {return d.key;})
// Change the selection
.selectAll('circle')
// Change the data to return index of nested array
.data(function(d) {return d.values;})
.enter().append('circle')
// Convert string date (which is the key in the nested array) to object and apply scale
.attr('cx', function(d) {return xScale(new Date(d.key));})
.attr('cy', function(d) { return yScale(d.values.averageScore); })
.attr('r', 5);
//Draw line
// 1. d3.svg.line() line generator takes values and retuns x/y c-oords for each datapoint
var subjectPath = d3.svg.line()
.x(function(d) {
return xScale(new Date(d.key));})
.y(function(d) {
return yScale(d.values.averageScore);
})
// 2. Select the subject group and append a path to each
svg.selectAll(".subject-group")
.data(nestedSubjectData)
.append('path')
.attr('class', 'subject-line')
.attr("d", subjectPath)
// Pass the second level of the nested array to subjectPath to generate x/y co-ords for the
.attr("d",function(d) {return subjectPath(d.values);});
有用的阅读:
jshanley's nested selection JS Bin - 与SO问题Accessing Nested Array in a D3 variable相关
关于arrays - 访问多维 D3 Nest() 汇总键和值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32349432/