Question

I'm trying to make a simple scatterplot visualization of academic salaries over time with data imported from a csv. Here's my Javascript:

  var w = 800;
  var h = 500;
  var padding = 50;
  var data = []
  d3.csv('salaries.csv', function(dset){
    data = dset.map(function(d) { 
      return [ 
      +d["Year"], 
      +d["MU_Professor"],
      +d["NAS_Professor"],
      d["Department"]
    ]; });
  });

  var xScale = d3.scale.linear()
      .domain([1989, 2009])
      .range([padding,w-padding]);
  var yScale = d3.scale.linear()
      .domain([0, 200000])
      .range([h-padding,padding]);
  var svg = d3.select("body")
     .append("svg")
     .attr('width',w)
     .attr('height',h);

  //Axes
  var xAxis = d3.svg.axis()
    .scale(xScale)
    .ticks(5)
    .tickFormat(d3.format("d"))
    .orient("bottom");
  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + (h - padding) + ")")
    .call(xAxis);

  var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left")
    .ticks(5);
  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + padding + ",0)")
    .call(yAxis);

  //Points
  svg.selectAll("g")
     .data(data)
     .enter()
     .append("circle")
     .attr("cx", function(d){
       return xScale(d[0]);
     })
     .attr("cy", function(d){
        return yScale(d[1]);
     })
     .attr("r", function(d){
        return 3;
     })
    .attr("id", function(d, i){
      return i;
    });

This code runs without error, but the points don't render on load. If I open up the Javascript console in my browser and then copy and paste the last code block (labeled //Points above) the points actually render.

Has anybody encountered this before? Can someone explain what about my code is causing this?

Was it helpful?

Solution

Yes - the problem is that your browser executes the 'points' block before your browser has a chance to load the CSV and draw the points to your canvas.

Let me explain.

Your browser executes the code from the top to the bottom, sequentially. This part -

d3.csv('salaries.csv', function(dset){
    data = dset.map(function(d) { 
      return [ 
      +d["Year"], 
      +d["MU_Professor"],
      +d["NAS_Professor"],
      d["Department"]
    ]; });
  });

Tells D3 to go off on its own and load the .csv - but before that finishes, the browser moves on and executes the rest of the code. This is an 'Asynchronous' method.

You could try moving the //points block into the same function that maps the points from the csv.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top