2

I am trying to build a choropleth using d3.js version 6 now. Here is my code in JavaScript:

var height = 300;

var projection = d3.geoMercator().center([145, -36.5])
                   .translate([width/2, height/2])
                   .scale(2450);

var color = d3.scaleQuantize().range(['#b2182b','#ef8a62','#fddbc7','#d1e5f0','#67a9cf','#2166ac']);


var path = d3.geoPath().projection(projection);

var svg = d3.select("body")
            .append("svg")
            .attr("width", width)
            .attr("height", height)
            .attr("fill", "grey");

d3.csv("files/VIC_LGA_unemployment.csv", function(data) {

    //Set input domain for color scale
    color.domain([
        d3.min(data, function(d) { return d.value; }), 
        d3.max(data, function(d) { return d.value; })
    ]);

    d3.json("files/LGA_VIC.json").then(function(json) {

        for (var i = 0; i < data.length; i++) {
    
            
            var data_LGA = data[i].LGA;
            
            //Grab data value, and convert from string to float
            var dataValue = parseFloat(data[i].unemployed);
    
       
            for (var j = 0; j < json.features.length; j++) {
            
                var json_LGA = json.features[j].properties.LGA_name;
    
                if (data_LGA == json_LGA) {
            
                    //Copy the data value into the JSON
                    json.features[j].properties.value = dataValue;
                    
                    //Stop looking through the JSON
                    break;
                    
                }
            }       
        }

        svg.selectAll("path")
            .data(json.features)
            .enter()
            .append("path")
            .attr("d", path)
            .style("fill", function(d) {
            //Get data value
                var value = d.properties.value;
                            
                if (value) {
                    //If value exists…
                    return color(value);
                } else {
                    //If value is undefined…
                    return "#ccc";
                }
            });
            
    });
            
});

However when I tried to run the visualisation on Firefox, it says that I have a TypeError (t is not iterable), like in this image:TypeError problem on the color domain.

Can anyone being familiar with choropleth in D3 help me with this problem?

Thank you!

Robin Mackenzie
  • 18,801
  • 7
  • 38
  • 56

1 Answers1

1

The answer is really a duplicate of this one, but the approach suggested here is maybe a cleaner way to do it.

The d3.csv (and d3.json) methods were changed between v4 and v5 to use the fetch API i.e. with Promises. Therefore the basic way you use the functions should change from:

d3.csv('file.csv', function(data) {...});

To:

d3.csv('file.csv')
  .then(function(data) {...})
  .catch(function(err) { console.log(err); });

Where D3 v6 is still using this way introduced in v5.

You are getting the t is not iterable error because the d3.min() (and max) functions use for...of over the array to figure out the answer, and at the time you call them, the Promise of the data has not yet resolved.

You're already using d3.json("files/LGA_VIC.json").then(function(json) { but maybe you can look into using Promise.all like this and then refactor your code:

Promise.all([
  d3.csv("./data.csv"),
  d3.json("./map.json")
])
.then(function([data, map]) {
  console.log(`There are ${data.length} rows of data`);
  console.log(`There are ${map.features.length} features in the geojson`);
  // ... join data to features and then draw chloropeth
});
Robin Mackenzie
  • 18,801
  • 7
  • 38
  • 56