简体   繁体   中英

d3 Axis Label Update

I have tried every permutation of this I can think of, but can not get the axis labels to clear and reset. I am creating a heatmap that updates via a dropdown menu. The graph shows up and the heatmap data draws correctly. The issue I am having is that every time the chart gets updated, all of the x-axis labels for the new data get appended as the data updates (but if I go back to a previously loaded set of data, it doesn't append it uses the old labels). I have tried to create a function that gets called when the dropdown changes that "clears" the graph and then calls another function to "redraw" it. I've tried to make the labels variables, and so on looking at a bunch of examples.

Even if I run a .remove() - and I have done this on the svg, the g, by g.class, etc. The axis labels just hang on, even though running the remove makes that DOM element disappear. It seems to have to do with the .exit .remove pattern, but I can't figure out the sequence? Any help would be great.

var dates = [];
var bacteria = [];

var itemHeight = 30,
  itemWidth = 12,
  cellSize = itemHeight - 1,
  margin = {
    top: 120,
    right: 20,
    bottom: 20,
    left: 80
  };

var e = document.getElementById("level");
var value = e.options[e.selectedIndex].value;
var text = e.options[e.selectedIndex].text;

var title = text.charAt(0).toUpperCase() + text.slice(1);
var newtitle = document.getElementById("thelevel").innerHTML=title;

d3.json("./javascripts/biome/biome_new.json").then(function(response) {
  var data = response;

  data.forEach(e => e.ubiome = e.ubiome.filter(e => e.tax_rank === value));

  dates = data.map(function(d) {
    return d.sample_date;
  })

  for (i = 0; i < data.length; i++) {
    bacteria.push(data[i].ubiome.slice(0, data[i].ubiome.length));
  }
  var bacteriaList = d3.merge(bacteria).map(function(d) {
    return d.tax_name
  });

  bacteriaList = d3.set(bacteriaList).values();

  var width = bacteriaList.length*itemWidth,
    height = 500 - margin.top - margin.bottom;

  var y_elements = dates,
    x_elements = bacteriaList;

  var xScale = d3.scaleBand()
    .domain(x_elements)
    .range([0, x_elements.length * itemWidth]);

  var xAxis = d3.axisTop()
    .scale(xScale)
    .tickFormat(function(d) {
      return d;
    });

  var yScale = d3.scaleBand()
    .domain(y_elements)
    .range([0, y_elements.length * itemHeight]);

  var yAxis = d3.axisLeft()
    .scale(yScale)
    .tickFormat(function(d) {
      return  moment(d).format("YYYY-MM-DD");
    });

  var colorScale = d3.scaleSequential(d3.interpolateOrRd)
    .domain([0, 10000]);

  var svg = d3.select('#heatmap')
    .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var parents = svg.selectAll('svg')
    .data(data)
    .enter().append('g')
    .attr("transform",function(d) { return "translate(0," + yScale(d.sample_date) + ")" });

  var children = parents.selectAll('rect')
    .data(function(d) { return d.ubiome; })
    .enter()
    .append('rect')
    .attr('class', 'cell')
    .attr('width', 15)
    .attr('height', cellSize)
    .attr('x', function(d) {  return xScale(d.tax_name); })
    .attr('fill', function(d) {
      return colorScale(d.count_norm);
    });

  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", "1.2em")
    .attr("transform", function(d) {
      return "rotate(-90)";
    });

    // Remove old elements
  parents.exit().remove();
  children.exit().remove();

});

function clearData(){
  bacteriaList = [];
  dates = [];

  var somemap = d3.selectAll("#heatmap");
  somemap.select("svg").remove();
  d3.select('#heatmap').html("");
  updateData();
}

function updateData(option) {
  var e = document.getElementById("level");
  var value = e.options[e.selectedIndex].value;
  var text = e.options[e.selectedIndex].text;

  var title = text.charAt(0).toUpperCase() + text.slice(1);
  var newtitle = document.getElementById("thelevel").innerHTML=title;

  d3.json("./javascripts/biome/biome_new.json").then(function(response) {
    var data = response;

    data.forEach(e => e.ubiome = e.ubiome.filter(e => e.tax_rank === value));

    dates = data.map(function(d) {
      return d.sample_date;
    })

    for (i = 0; i < data.length; i++) {
      bacteria.push(data[i].ubiome.slice(0, data[i].ubiome.length));
    }
    var bacteriaList = d3.merge(bacteria).map(function(d) {
      return d.tax_name
    });

    bacteriaList = d3.set(bacteriaList).values();

    var width = bacteriaList.length*itemWidth,
      height = 500 - margin.top - margin.bottom;

    var y_elements = dates,
      x_elements = bacteriaList;

    var xScale = d3.scaleBand()
      .domain(x_elements)
      .range([0, x_elements.length * itemWidth]);

    var xAxis = d3.axisTop()
      .scale(xScale)
      .tickFormat(function(d) {
        return d;
      });

    var yScale = d3.scaleBand()
      .domain(y_elements)
      .range([0, y_elements.length * itemHeight]);

    var yAxis = d3.axisLeft()
      .scale(yScale)
      .tickFormat(function(d) {
        return  moment(d).format("YYYY-MM-DD");
      });

    var colorScale = d3.scaleSequential(d3.interpolateOrRd)
      .domain([0, 10000]);

    var svg = d3.select('#heatmap')
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var parents = svg.selectAll('svg')
      .data(data)
      .enter().append('g')
      .attr("transform",function(d) { return "translate(0," + yScale(d.sample_date) + ")" });

    var children = parents.selectAll('rect')
      .data(function(d) { return d.ubiome; })
      .enter()
      .append('rect')
      .attr('class', 'cell')
      .attr('width', 15)
      .attr('height', cellSize)
      .attr('x', function(d) {  return xScale(d.tax_name); })
      .attr('fill', function(d) {
        return colorScale(d.count_norm);
      });

    var they = svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .selectAll('text')
      .attr('font-weight', 'normal');

    var thex = svg.append("g")
      .attr("class", "x axis")
      .call(xAxis)
      .selectAll('text')
      .attr('font-weight', 'normal')
      .style("text-anchor", "start")
      .attr("dx", ".8em")
      .attr("dy", "1.2em")
      .attr("transform", function(d) {
        return "rotate(-90)";
      });

      they.exit().remove();
      thex.exit().remove();

  });
}

 var data = [{ "sample_date": "2017-07-04T00:00:00.000Z", "ubiome": [ { "taxon": 1, "parent": 0, "count": 56085, "count_norm": 999999, "tax_name": "root", "tax_rank": "root" }, { "taxon": 2, "parent": 131567, "count": 56085, "count_norm": 999999, "tax_name": "Bacteria", "tax_rank": "superkingdom" }, { "taxon": 237, "parent": 49546, "count": 284, "count_norm": 5063, "tax_name": "Flavobacterium", "tax_rank": "genus" }, { "taxon": 543, "parent": 91347, "count": 21, "count_norm": 374, "tax_name": "Enterobacteriaceae", "tax_rank": "family" }, { "taxon": 579, "parent": 543, "count": 21, "count_norm": 374, "tax_name": "Kluyvera", "tax_rank": "genus" }, { "taxon": 712, "parent": 135625, "count": 2, "count_norm": 35, "tax_name": "Pasteurellaceae", "tax_rank": "family" }, { "taxon": 724, "parent": 712, "count": 2, "count_norm": 35, "tax_name": "Haemophilus", "tax_rank": "genus" }, { "taxon": 729, "parent": 724, "count": 2, "count_norm": 35, "tax_name": "Haemophilus parainfluenzae", "tax_rank": "species" }, { "taxon": 815, "parent": 171549, "count": 14662, "count_norm": 261424, "tax_name": "Bacteroidaceae", "tax_rank": "family" }, { "taxon": 816, "parent": 815, "count": 14625, "count_norm": 260764, "tax_name": "Bacteroides", "tax_rank": "class" } ] }, { "sample_date": "2017-07-10T00:00:00.000Z", "ubiome": [ { "taxon": 357276, "parent": 816, "count": 5150, "count_norm": 76679, "tax_name": "Bacteroides dorei", "tax_rank": "species" }, { "taxon": 360807, "parent": 841, "count": 60, "count_norm": 893, "tax_name": "Roseburia inulinivorans", "tax_rank": "species" }, { "taxon": 371599, "parent": 816, "count": 3, "count_norm": 44, "tax_name": "Bacteroides sp. XB12B", "tax_rank": "species" }, { "taxon": 375288, "parent": 171551, "count": 1357, "count_norm": 20204, "tax_name": "Parabacteroides", "tax_rank": "genus" }, { "taxon": 376806, "parent": 816, "count": 1050, "count_norm": 15633, "tax_name": "Bacteroides gallinarum", "tax_rank": "species" }, { "taxon": 387661, "parent": 375288, "count": 941, "count_norm": 14010, "tax_name": "Parabacteroides johnsonii", "tax_rank": "species" }, { "taxon": 397864, "parent": 171551, "count": 891, "count_norm": 13266, "tax_name": "Barnesiella", "tax_rank": "genus" }, { "taxon": 418240, "parent": 572511, "count": 801, "count_norm": 11926, "tax_name": "Blautia wexlerae", "tax_rank": "species" }, { "taxon": 420345, "parent": 31979, "count": 14, "count_norm": 208, "tax_name": "Lactonifactor", "tax_rank": "class" } ] } ]; var dates = []; var bacteria = []; var itemHeight = 30, itemWidth = 12, cellSize = itemHeight - 1, margin = { top: 120, right: 20, bottom: 20, left: 80 }; var e = document.getElementById("level"); var value = e.options[e.selectedIndex].value; var text = e.options[e.selectedIndex].text; var title = text.charAt(0).toUpperCase() + text.slice(1); var newtitle = document.getElementById("thelevel").innerHTML=title; //d3.json("./javascripts/biome/biome_new.json").then(function(response) { data.forEach(e => e.ubiome = e.ubiome.filter(e => e.tax_rank === value)); dates = data.map(function(d) { return d.sample_date; }); for (i = 0; i < data.length; i++) { bacteria.push(data[i].ubiome.slice(0, data[i].ubiome.length)); } var bacteriaList = d3.merge(bacteria).map(function(d) { return d.tax_name }); bacteriaList = d3.set(bacteriaList).values(); var width = bacteriaList.length*itemWidth, height = 500 - margin.top - margin.bottom; var y_elements = dates, x_elements = bacteriaList; var xScale = d3.scaleBand() .domain(x_elements) .range([0, x_elements.length * itemWidth]); var xAxis = d3.axisTop() .scale(xScale) .tickFormat(function(d) { return d; }); var yScale = d3.scaleBand() .domain(y_elements) .range([0, y_elements.length * itemHeight]); var yAxis = d3.axisLeft() .scale(yScale) .tickFormat(function(d) { return moment(d).format("YYYY-MM-DD"); }); var colorScale = d3.scaleSequential(d3.interpolateOrRd) .domain([0, 10000]); var svg = d3.select('#heatmap') .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var parents = svg.selectAll('svg') .data(data) .enter().append('g') .attr("transform",function(d) { return "translate(0," + yScale(d.sample_date) + ")" }); var children = parents.selectAll('rect') .data(function(d) { return d.ubiome; }) .enter() .append('rect') .attr('class', 'cell') .attr('width', 15) .attr('height', cellSize) .attr('x', function(d) { return xScale(d.tax_name); }) .attr('fill', function(d) { return colorScale(d.count_norm); }); 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", "1.2em") .attr("transform", function(d) { return "rotate(-90)"; }); // Remove old elements parents.exit().remove(); children.exit().remove(); //}); function clearData(){ bacteriaList = []; dates = []; var somemap = d3.selectAll("#heatmap"); somemap.select("svg").remove(); d3.select('#heatmap').html(""); updateData(); } function updateData() { var data = [{ "sample_date": "2017-07-04T00:00:00.000Z", "ubiome": [ { "taxon": 1, "parent": 0, "count": 56085, "count_norm": 999999, "tax_name": "root", "tax_rank": "root" }, { "taxon": 2, "parent": 131567, "count": 56085, "count_norm": 999999, "tax_name": "Bacteria", "tax_rank": "superkingdom" }, { "taxon": 237, "parent": 49546, "count": 284, "count_norm": 5063, "tax_name": "Flavobacterium", "tax_rank": "genus" }, { "taxon": 543, "parent": 91347, "count": 21, "count_norm": 374, "tax_name": "Enterobacteriaceae", "tax_rank": "family" }, { "taxon": 579, "parent": 543, "count": 21, "count_norm": 374, "tax_name": "Kluyvera", "tax_rank": "genus" }, { "taxon": 712, "parent": 135625, "count": 2, "count_norm": 35, "tax_name": "Pasteurellaceae", "tax_rank": "family" }, { "taxon": 724, "parent": 712, "count": 2, "count_norm": 35, "tax_name": "Haemophilus", "tax_rank": "genus" }, { "taxon": 729, "parent": 724, "count": 2, "count_norm": 35, "tax_name": "Haemophilus parainfluenzae", "tax_rank": "species" }, { "taxon": 815, "parent": 171549, "count": 14662, "count_norm": 261424, "tax_name": "Bacteroidaceae", "tax_rank": "family" }, { "taxon": 816, "parent": 815, "count": 14625, "count_norm": 260764, "tax_name": "Bacteroides", "tax_rank": "class" } ] }, { "sample_date": "2017-07-10T00:00:00.000Z", "ubiome": [ { "taxon": 357276, "parent": 816, "count": 5150, "count_norm": 76679, "tax_name": "Bacteroides dorei", "tax_rank": "species" }, { "taxon": 360807, "parent": 841, "count": 60, "count_norm": 893, "tax_name": "Roseburia inulinivorans", "tax_rank": "species" }, { "taxon": 371599, "parent": 816, "count": 3, "count_norm": 44, "tax_name": "Bacteroides sp. XB12B", "tax_rank": "species" }, { "taxon": 375288, "parent": 171551, "count": 1357, "count_norm": 20204, "tax_name": "Parabacteroides", "tax_rank": "genus" }, { "taxon": 376806, "parent": 816, "count": 1050, "count_norm": 15633, "tax_name": "Bacteroides gallinarum", "tax_rank": "species" }, { "taxon": 387661, "parent": 375288, "count": 941, "count_norm": 14010, "tax_name": "Parabacteroides johnsonii", "tax_rank": "species" }, { "taxon": 397864, "parent": 171551, "count": 891, "count_norm": 13266, "tax_name": "Barnesiella", "tax_rank": "genus" }, { "taxon": 418240, "parent": 572511, "count": 801, "count_norm": 11926, "tax_name": "Blautia wexlerae", "tax_rank": "species" }, { "taxon": 420345, "parent": 31979, "count": 14, "count_norm": 208, "tax_name": "Lactonifactor", "tax_rank": "class" } ] } ]; var e = document.getElementById("level"); var value = e.options[e.selectedIndex].value; var text = e.options[e.selectedIndex].text; var title = text.charAt(0).toUpperCase() + text.slice(1); var newtitle = document.getElementById("thelevel").innerHTML=title; //d3.json("./javascripts/biome/biome_new.json").then(function(response) { //var data = response; data.forEach(e => e.ubiome = e.ubiome.filter(e => e.tax_rank === value)); dates = data.map(function(d) { return d.sample_date; }); for (i = 0; i < data.length; i++) { bacteria.push(data[i].ubiome.slice(0, data[i].ubiome.length)); } var bacteriaList = d3.merge(bacteria).map(function(d) { return d.tax_name }); bacteriaList = d3.set(bacteriaList).values(); var width = bacteriaList.length*itemWidth, height = 500 - margin.top - margin.bottom; var y_elements = dates, x_elements = bacteriaList; var xScale = d3.scaleBand() .domain(x_elements) .range([0, x_elements.length * itemWidth]); var xAxis = d3.axisTop() .scale(xScale) .tickFormat(function(d) { return d; }); var yScale = d3.scaleBand() .domain(y_elements) .range([0, y_elements.length * itemHeight]); var yAxis = d3.axisLeft() .scale(yScale) .tickFormat(function(d) { return moment(d).format("YYYY-MM-DD"); }); var colorScale = d3.scaleSequential(d3.interpolateOrRd) .domain([0, 10000]); var svg = d3.select('#heatmap') .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var parents = svg.selectAll('svg') .data(data) .enter().append('g') .attr("transform",function(d) { return "translate(0," + yScale(d.sample_date) + ")" }); var children = parents.selectAll('rect') .data(function(d) { return d.ubiome; }) .enter() .append('rect') .attr('class', 'cell') .attr('width', 15) .attr('height', cellSize) .attr('x', function(d) { return xScale(d.tax_name); }) .attr('fill', function(d) { return colorScale(d.count_norm); }); var they = svg.append("g") .attr("class", "y axis") .call(yAxis) .selectAll('text') .attr('font-weight', 'normal'); var thex = svg.append("g") .attr("class", "x axis") .call(xAxis) .selectAll('text') .attr('font-weight', 'normal') .style("text-anchor", "start") .attr("dx", ".8em") .attr("dy", "1.2em") .attr("transform", function(d) { return "rotate(-90)"; }); they.exit().remove(); thex.exit().remove(); //}); } 
 body { padding: 50px; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .column { float: left; width: 20%; } /* Clear floats after the columns */ .row:after { content: ""; display: table; clear: both; } #heatmap { height: 400px; width: 1200px; border:2px solid #000; overflow: scroll; padding: 20px; } 
 <!DOCTYPE html> <html> <head> <title></title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta charset="utf-8"> <link rel="stylesheet" href="/stylesheets/style.css"> </head> <body> <content> <h1></h1> <h4>Sort by:</h4> <div class="row"> <div class="column"><select id="level" style="margin-bottom:20px;" onchange="clearData()"><option value="class">Class</option><option value="family">Family</option><option value="genus">Genus</option><option value="order">Order</option><option value="phylum">Phylum</option><option value="species">Species</option><option value="subclass">Subclass</option><option value="suborder">Suborder</option><option value="subphylum">Subphylum</option><option value="superphylum">Superphylum</option></select></div> <div class="column"> <div id="thelevel"></div> </div> </div> <div id="heatmap"></div> </content> </body> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script> </html> 

For those that come across this, I finally figured it out myself.

The issue had to do with how the array was being stored, and may have nothing to do with d3.

Once I updated the original variable in the update function to:

bacteria.length = 0;

...everything fell into place. That initial array was just hanging on. Once I reset it, the update function was able to rebuild everything just fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM