I am creating a choropleth map in d3 v6, but the map is showing only one color. I want the map to be covered based on total_cases. This is the code I am using:
// The svg
const margin ={ top: 500, bottom: 500, left: 100, right: 0},
width = 600,
height = 500;
//Choropleth Map
const svg1 = d3.select('body')
.append('svg')
.attr('width', width margin.left margin.right)
.attr('height', height margin.top margin.bottom)
// Map and projection
const path = d3.geoPath();
const projection = d3.geoMercator()
.scale(70)
.center([0,20])
.translate([width / 2, height / 2]);
// Data and color scale
const data = new Map();
const colorScale = d3.scaleThreshold()
.domain([0, 300000000])
.range(d3.schemeBlues[9]);
// Load external data and boot
Promise.all([
d3.json("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson"),
d3.csv("mapdata.csv", function(d) {
data.set(d.country, d.total_cases_per_million);
})
]).then(function(loadData){
let topo = loadData[0]
console.log(data);
let mouseOver = function(d) {
d3.selectAll(".Country")
.transition()
.duration(200)
.style("opacity", .5)
d3.select(this)
.transition()
.duration(200)
.style("opacity", 1)
.style("stroke", "black")
}
let mouseLeave = function(d) {
d3.selectAll(".Country")
.transition()
.duration(200)
.style("opacity", .8)
d3.select(this)
.transition()
.duration(200)
.style("stroke", "transparent")
}
// Draw the map
svg1.append("g")
.selectAll("path")
.data(topo.features)
.enter()
.append("path")
// draw each country
.attr("d", d3.geoPath()
.projection(projection)
)
// set the color of each country
.attr("fill", function (d) {
d.total = data.get(data.total_cases_per_million) || 0;
return colorScale(d.total);
})
.style("stroke", "transparent")
.attr("class", function(d){ return "Country" } )
.style("opacity", .8)
.on("mouseover", mouseOver )
.on("mouseleave", mouseLeave )
})
This is how the map looks and I don't get any error message on the console. Would really appreciate it if someone could help me out!
This is how the map looks and I don't get any error message on the console. Would really appreciate it if someone could help me out!
EDIT: The csv file looks like this
iso_code,country,total_cases_per_million
AFG,Afghanistan,2917418.02
ALB,Albania,58135447.4
DZA,Algeria,3715179.438
AND,Andorra,270897098
CodePudding user response:
In the Map object, you set the country name as the key:
data.set(d.country, d.total_cases_per_million);
Also, in the GeoJSON, the country name is found under properties.name
for each feature.
Therefore, this is how you should fill the paths:
.attr("fill", function (d) {
d.total = data.get(d.properties.name) || 0;
return colorScale(d.total);
})
The CSV you pasted is incorrect, it has spaces after the numbers, check that.
Finally, the threshold scale is not the adequate choice, even more given that you have only two values in the domain. You can use a linear scale, or, most commonly used in choropleths, a quantile or a quantize scale. You can still use a threshold scale, but set the thresholds adequately.