d3.js Heatmap嵌套JSON

时间:2018-06-21 23:03:07

标签: javascript json d3.js

我只是想不通。一直盯着教程,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);

向正确的方向轻推将是极好的!

0 个答案:

没有答案