Palucca
Palucca

Reputation: 35

D3 Projection function returns NaN when given a latitude and longitude (Mapping csv data on a geoJSON map)

I am currently working on a project where I want to visualize airport locations in the USA on a geoJSON map and where the state is encoded by color.

So far I have managed to import my geoJSON file of US borders and my csv file of my airports dataset just fine. Furthermore, I have been able to visualize the map and adjusted the styling to my liking with the help of these ressources:

Observable - Making maps in D3

Making Bubble Maps in D3

Now I want to add the airport locations. My csv file that contains the list of airports includes a state abbreviation and latitude/longitude coordinates to help with the mapping. Since the first ressource mentioned above uses geoJSON to add the data, which is not available for me since I only have an csv file, I decided to go with the second tutorial to add my data to the map. However, when I try to project my longitude and latitude coordinates to carthesian coordinates, like in the example, nothing happens.

Just to check I have written a piece of code that logs the projected longitude and latitude arrays in the console and I realized that the function does indeed return an array of length 2 for each coordinate, but instead of storing a numerical value I get 'NaN' which does not cause an error when trying to add the data to the map but also doesn't make any dots show up on my map, naturally.

I have tried to look for solutions but couldn't find anything regarding this issue. The projection function works fine when using it for the map, so i don't quite understand why it does not work for the dataset as well.

You can take a look at my js file below. I had to remove the links for the actual datasets because they belong to my university and I am pretty sure I am not allowed to make them public. I also removed some code that I considered redundant from the snippet like specific values to allow for a better overview.

Also, I use D3 v5 (requirement from my university).

/* ===== Draw Map of the United States Part begins here ===== */
  /* ===== USStates GeoJson =====*/
  //load US states geo.json file from assets folder
  d3.json("Imagine_Actual_link_here.json")
  .then(function(states){
    
    /* ===== Create svg canvas for said file =====*/  
    
    // set size of canvas
    // specifies height and width of the canvas
    
    // Create the svg Element
    let svg = d3.select(".map")
      .append("svg")
      .attr("width", width)
      .attr("height", height);
    
    // Append empty placeholder g element to the SVG canvas
    svg.append("g");
    
    /* ===== Set Up Projection an draw paths ===== */
    
    // Projection
    var projection = d3.geoAlbers()
      //scaling, rotating, etc.
    
    
    // Create GeoPath that draws path
    var dataGeoPath = d3.geoPath()
      .projection(projection);
    
    svg.selectAll("path")
      .data(states.features)
      .enter()
      .append("path")
      .attr("fill", "#ccc")
      .attr("stroke", "#fff")
      .attr("d", dataGeoPath);

    /* ===== Draw Map of the United States Part end here ===== */


    
    /* ===== Visualize the flight data Part begins here ===== */  
    
    /* ===== Load the data sets from the assets folder ===== */
    // Load Airports data
      d3.csv("Imagine_Another_link_here.html").then(function(airports){
                  

          
          //Create Colour Scale for all 50 States
          var color = d3.scaleOrdinal()
            // color scale for the states, not important right now, priority is fixing the coordinate issue
          
          
          
          // Everything works fine so far!
          // Now this is where things get complicated!  
        
          // Example loop to check return of projection function
          airports.forEach((d) => {
            console.log(projection([+d.longitude]), projection([+d.latitude]));
          });
          
    

          // Append Airports data to map 
          svg
            .selectAll("myCircles")
            .data(airports)
            .enter().append("circle")
              .attr("cx", function(d){ return projection([+d.longitude, +d.latitude])[0]})  //!! tries to add NaN as a value for x-axis
              .attr("cy", function(d){ return projection([+d.longitude, +d.latitude])[1]})  //!! tries to add NaN as a value for the y axis
              .attr("stroke-width", 1)
              .attr("fill-opacity", .4)
              //.style("fill", function(d){ return color(d.state)})
              //.attr("stroke", function(d){ return color(d.state)})
        
        
      });
        
         
    /* ===== Visualize the flight data Part ends here ===== */  
    
    // Return the visualisation of the map
    return svg.node();
    
  
  });

Feel free to ask any questions if anything about my code is unclear.

Upvotes: 2

Views: 257

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

You need to pass a two-element array to the projection:

console.log(projection([+d.longitude, +d.latitude])

Upvotes: 1

Related Questions