Philipp_Kats
Philipp_Kats

Reputation: 4214

Combine geojson and csv, then use new data to style the map

I am trying to write a general-purpose map so that any new csv will change the data visualization. I was able to plot the map, join csv with geojson and even print csv data on mouseover. However, when I try to use this data to apply colors to the map, I get undefined all the time - I guess due to the asynchronous nature of js. How can I fix that most efficiently?

Here is my code:

//  Community colors
var comm_colors = [ "red", "blue", "green", "yellow", "purple" ];

// CSV
function parse_add_csv(cts){

  var new_cts = cts
  console.log('parsing csv');
  d3.csv("data/communities.csv", function(comms)
      { csv = comms.map(function(d)
          {

              return {"community": d.community, "label": d.BoroCT2010} ;
          })

          csv.forEach(function(d, i) {
            new_cts.forEach(function(e, j) {
          if (d.label === e.properties.BoroCT2010) {

              e.properties.community = parseInt(d.community)
              }
            })
          })
    })
    return new_cts
  }


d3.json("data/nyct2010_17a3_topo.json", function(error, nyb) {
  console.log('tracts uploaded, v3')

  var ctss = topojson.feature(nyb, nyb.objects.nyct2010_17a3).features;
  ctss = parse_add_csv(ctss);  // match data from csv by BoroCT2010

  cts.selectAll(".tract")
      .data(ctss)
      .enter().append("path")
      .attr("class", "tract")
      .attr("d", path)
      .attr("id", function(d) {
        return d.properties.BoroCT2010;})
      .attr("nhd_name", function(d) {
        return d.properties.NTAName;})
      .style('fill', function(d){
          console.log(comm_colors[d.properties.community])
          return comm_colors[d.properties.community];})
      .on("mouseover", handleMouseOver)
      .on("mouseout", handleMouseOut)
      .style('fill', function(d) {return 
             comm_colors[d.properties.community]});
})

Here, I am trying to match community column from csv to the geojson and then use it to select a color from the list. It works perfectly when I print color in the mouseover event but does not work within the chain:

.style('fill', function(d){
              console.log(comm_colors[d.properties.community])
              return comm_colors[d.properties.community];})

Upvotes: 1

Views: 1222

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102198

Your guess is only partially correct:

I get undefined all the time - I guess due to the asynchronous nature of js.

There is no "asynchronous nature of js". JavaScript is always synchronous and single-threaded. However, AJAX calls and D3 functions like d3.json and d3.csv are asynchronous.

That being said, there are a couple of solutions. You can use d3.queue. The easiest solution, though, is simply nesting the asynchronous functions:

d3.json("data/nyct2010_17a3_topo.json", function(error, nyb){
    d3.csv("data/communities.csv", function(comms){
        //here goes all code that uses both 'nyb' and 'comms'
    })
})

After nesting them, put all the code that deals with the GeoJSON and with the CSV inside the inner callback.

Upvotes: 1

Related Questions