我只是想不通。一直盯着教程,SO问题以及文档。只是没有点击。
我正在尝试在d3中构建一些嵌套JSON数据的热图。我按照这些教程进行操作,并使用一组未嵌套的数据创建它没有问题。但是我正在努力弄清楚如何将这些嵌套数据强制到“正确的位置”。我只是从使用d3开始,我已经阅读了一条学习曲线-我只是想不通这种关系如何工作。
这是我的数据(缩写):
let data = [
{
"sample_date": "2017-07-04T00:00:00.000Z",
"ubiome": [
{
"count_norm": 1283,
"tax_name": "Bacteroides fragilis",
"tax_rank": "species"
},
{
"count_norm": 3708,
"tax_name": "Bacteroides thetaiotaomicron",
"tax_rank": "species"
},
{
"count_norm": 731,
"tax_name": "Bacteroides uniformis",
"tax_rank": "species"
},
{
"count_norm": 62226,
"tax_name": "Bacteroides vulgatus",
"tax_rank": "species"
},
{
"count_norm": 2139,
"tax_name": "Parabacteroides distasonis",
"tax_rank": "species"
}
]
},
{
"sample_date": "2017-07-04T00:00:00.000Z",
"ubiome": [
{
"count_norm": 1283,
"tax_name": "Bacteroides fragilis",
"tax_rank": "species"
},
{
"count_norm": 3708,
"tax_name": "Bacteroides thetaiotaomicron",
"tax_rank": "species"
},
{
"count_norm": 731,
"tax_name": "Bacteroides uniformis",
"tax_rank": "species"
},
{
"count_norm": 62226,
"tax_name": "Bacteroides vulgatus",
"tax_rank": "species"
},
{
"count_norm": 2139,
"tax_name": "Parabacteroides distasonis",
"tax_rank": "species"
}
]
}
]
我正在尝试创建一个热图,其中沿x轴带有采样日期,沿y带有细菌名称。计数用于确定“颜色”。
我看过:
...等等。
我试图修改代码以使其适合并使其正常工作,但我似乎无法找到正确的对象/数组路径来获取数据以加载y轴(细菌名称)。我被困在如何遍历“ ubiome”集以构建轴标签以及访问“ counts”以填充矩形的问题上。在上面列出了嵌套数据结构的示例中,我可以使用正确的信息构建ul / li列表,但是我似乎无法对其进行调整以适应x / y的要求并为其加载热图可视化\ format。我可以使该示例使用1组数据(https://bl.ocks.org/Bl3f/cdb5ad854b376765fa99),但是一旦尝试使用嵌套数据,它们就会全部崩溃,并且会出现未定义,属性访问错误或空白数据的情况。
最后,我将有一个下拉菜单,其中包含“ tax_rank”作为选项,并且热图将按等级重新加载,因此HTML中的onchange函数将调用该函数来加载热图。
我的代码很乱,所以我很抱歉没有发布工作集-但下面的内容表明我一直在努力解决这一问题。这是一个例子。
var xScale = d3.scale.linear()
.domain(x_elements) ///This is where I know the sample_date.length value comes into play.
.rangeBands([0, x_elements.length * itemSize]);
var xAxis = d3.svg.axis()
.scale(xScale)
.tickFormat(function (d) {
return d;
})
.orient("top");
var yScale = d3.scale.ordinal()
.domain(y_elements) //This is the one I have no clue how to get at the actual data
.rangeBands([0, y_elements.length * itemSize]);
var yAxis = d3.svg.axis()
.scale(yScale)
.tickFormat(function (d) {
return d;
})
.orient("left");
var svg = d3.select(".chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", (y_elements.length * itemSize) + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var cells = svg.selectAll('rect')
.data(data)
.enter().append('g').append('rect')
.attr('class', 'cell')
.attr('width', cellSize)
.attr('height', cellSize)
.attr('y', function(d) { return yScale(d.sample_date); })
.attr('x', function(d) { return xScale(d[ubiome].tax_name); })//// This I know must be iterated through. I have seen some examples using an each and looping back through more nested data, but I don't know how to get at that.
.attr('fill', function(d) { return colorScale(d.value); });
////This is just from the example, and I can sort this out once I know where/how to get at the scales and axis in d3
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll('text')
.attr('font-weight', 'normal')
svg.append("g")
.attr("class", "x axis")
.call(xAxis)
.selectAll('text')
.attr('font-weight', 'normal')
.style("text-anchor", "start")
.attr("dx", ".8em")
.attr("dy", ".5em")
.attr("transform", function (d) {
return "rotate(-65)";
});
var legend = d3.select(".legend");
legend.enter().append("g")
.attr("class", "legend")
.data([0,1,2,3,4,5,6,7,8,9,10]);
legend.append("rect")
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height)
.attr("width", legendElementWidth)
.attr("height", gridSize)
.style("fill", function(d, i) { return colors[i]; });
legend.append("text")
.attr("class", "mono")
.text(function(d) { return "≥ " + Math.round(d); })
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + gridSize*2);
向正确的方向轻推将是极好的!