Choropleth map using D3.js and CSV file - javascript
I am using d3.js in a project for university where I have to visualize the world Choropleth world MAP passing the data to color the country form a file csv internally built this way:
nationality,victims
Austria,4500
France,1345
China,16000000
Italy,452345
Hungary,70000
and so on.
Until I create only the world map it works and a map will show on the web.
When I add the d3.csv part to read data it shows nothing.
I attached the code below:
function mapRender(){
var width = 900;
var height = 550;
//Select the div to show the maps
var svg = d3.select("#map")
.append("svg")
.attr("width", width)
.attr("height", height)
.append('g')
//Setting the color domains for the choropleth maps
var color = d3.scaleThreshold()
.domain([0, 50000, 100000, 150000, 200000, 500000, 1000000, 5000000, 10000000, 20000000])
.range(["#ffff00", "#FFF933", "#DCFF33", "#97FF33", "#40FF33", "#33FFA7", "#33FFFB", "#33AAFF", "#336EFF"]);
var projection = d3.geoMercator()
.scale(125)
.translate([width / 2, height / 1.4]);
var path = d3.geoPath().projection(projection);
d3.json("https://unpkg.com/world-atlas#1/world/110m.json", function (error, world) {
if (error) throw error;
//Load data from CSV file
d3.csv("../datasets/csv/choropleth.csv", function (data) {
var dataByName = {};
data.forEach(function (d) {
dataByName[d.nationality] = +d.victims;
});
svg.append("path")
.datum(topojson.feature(world, world.objects.land))
.append("path")
.attr("d", path)
.attr("fill", function(d) {
return color(dataByName[d.nationality]);
});
// .attr("fill", "#000000")
// .attr("d", path);
})
})
}
Anyone that can help me to understand why it doesn't work?
Related
Choropleth Not Displaying
I'm working on a project in d3.js, and I can't seem to make my map work. Every time I run it there are no syntax errors, but there's only a blank screen. Here's the code: <svg id="my_dataviz" width="1000" height="1000"></svg> <script> // The svg var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); // Map and projection var path = d3.geoPath(); var projection = d3.geoMercator() .scale(10000) .center([30, -85]) .translate([width / 2, height / 2]); // Data and color scale var data = d3.map(); var colorScale = d3.scaleThreshold() .domain([-5000, -3000, -1000, 1000, 3000, 5000]) .range(d3.schemeReds[7]); // Load external data and boot d3.queue() .defer(d3.json, "G2.geojson") .defer(d3.csv, "ps.csv", function(d) { data.set(d.GEOID20, +d.PRE_SC); }) .await(ready); function ready(error, topo) { // Draw the map svg.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(d.id) || 0; return colorScale(d.total); }); } </script> </body> </html> I made sure that my projection was WGS 84. If I have any errors in the code please let me know! Thank you all!
D3.js svg does not draw Map
I am trying to draw maps using D3.js. The GeoJson file is converted from shapefile and stored in the project folder. The GeoJson data format: {"type":"FeatureCollection", "features": [{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[31.287890625000017,-22.40205078125001],[31.429492187500017,-22.298828125],[31.57148437500001,-22.15351562500001],[31.737695312500023,-21.9833984375],[31.88593750000001,-21.83154296875],[32.01630859375001,-21.698046875000003],[32.19472656250002,-21.515429687500003],[32.37109375,-21.33486328125001],[32.41240234375002,-21.311816406250003],[32.429785156250006,-21.29707031250001],[32.353613281250006,-21.136523437500003],[32.476171875000006,-20.95009765625001],[32.48281250000002,-20.828906250000003],[32.477636718750006,-20.712988281250006],[32.49238281250001,-20.659765625000006],[32.529296875,-20.613085937500003],[32.67255859375001,-20.51611328125],[32.780859375000006,-20.36152343750001],[32.86962890625,-20.21718750000001],[32.992773437500006,-19.98486328125],[33.0048828125,-19.93017578125],[33.00673828125002,-19.873828125000003],[32.97265625,-19.79541015625],[32.89042968750002,-19.668066406250006],[32.83076171875001,-19.558203125000006],[32.77763671875002,-19.388769531250006],[32.83095703125002,-19.24140625000001],[32.85000000000002,-19.152441406250006],[32.84980468750001,-19.10439453125001],[32.826171875,-19.05878906250001],[32.766210937500006,-19.02431640625001],[32.71650390625001,-19.00185546875001],[32.69970703125,-18.94091796875],[32.69921875,-18.868457031250003],[32.72197265625002,-18.828417968750003],[32.8544921875,-18.763671875],[32.88457031250002,-18.728515625],[32.90029296875002,-18.689062500000006],[32.90166015625002,-18.632910156250006],[32.942480468750006,-18.49267578125],[32.99306640625002,-18.35957031250001],[32.99638671875002,-18.312597656250006],[32.978515625,-18.271484375],[32.96464843750002,-18.1962890625],[32.95556640625,-18.08291015625001],[32.954687500000006,-17.765429687500003],[32.98076171875002,-17.4375],[32.969335937500006,-17.251562500000006],[32.884375000000006,-17.03779296875001],[32.87626953125002,-16.883593750000003],[32.93789062500002,-16.775976562500006],[32.94804687500002,-16.71230468750001],[32.902929687500006,-16.704199218750006],[32.81025390625001,-16.69765625000001],[32.741796875000006,-16.67763671875001],[32.635839843750006,-16.589453125000006],[32.45195312500002,-16.515722656250006],[32.243261718750006,-16.44873046875],[31.939843750000023,-16.428808593750006],[31.687597656250006,-16.214160156250003],[31.489843750000006,-16.1796875],[31.426171875000023,-16.15234375],[31.236230468750023,-16.02363281250001],[30.938769531250017,-16.01171875],[30.630175781250017,-15.999218750000011],[30.437792968750017,-15.995312500000011],[30.40937500000001,-15.978222656250011],[30.39814453125001,-15.80078125],[30.396093750000006,-15.64306640625],[30.25068359375001,-15.643457031250009],[29.994921875000017,-15.64404296875],[29.729589843750006,-15.644628906250006],[29.4873046875,-15.69677734375],[29.287890625000017,-15.776464843750006],[29.050585937500017,-15.901171875000003],[28.973046875000023,-15.950097656250009],[28.9130859375,-15.98779296875],[28.875585937500006,-16.0361328125],[28.856738281250017,-16.14228515625001],[28.856738281250017,-16.30615234375],[28.83271484375001,-16.424121093750003],[28.760546875000017,-16.53212890625001],[28.760644531250023,-16.53193359375001],[28.399804687500023,-16.66279296875001],[28.16376953125001,-16.76972656250001],[27.932226562500006,-16.89619140625001],[27.75654296875001,-17.060351562500003],[27.63671875,-17.26210937500001],[27.437890625000023,-17.51191406250001],[27.235742187500023,-17.728320312500003],[27.020800781250017,-17.95839843750001],[26.779882812500006,-18.04150390625],[26.577539062500023,-18.022558593750006],[26.333398437500023,-17.929296875000006],[26.139550781250023,-17.911718750000006],[25.995898437500017,-17.969824218750006],[25.86328125,-17.951953125000003],[25.741601562500023,-17.858203125000003],[25.6396484375,-17.82412109375001],[25.55712890625,-17.84951171875001],[25.451757812500006,-17.84511718750001],[25.2587890625,-17.793554687500006],[25.239062500000017,-17.843066406250003],[25.224023437500023,-17.91523437500001],[25.242285156250006,-17.969042968750003],[25.28242187500001,-18.04121093750001],[25.340234375000023,-18.1044921875],[25.384375000000006,-18.14199218750001],[25.43671875000001,-18.234960937500006],[25.4892578125,-18.35126953125001],[25.55830078125001,-18.44179687500001],[25.76123046875,-18.649218750000003],[25.78369140625,-18.72353515625001],[25.811914062500023,-18.79707031250001],[25.939355468750023,-18.93867187500001],[25.95917968750001,-18.985644531250003],[25.95068359375,-19.08173828125001],[26.081933593750023,-19.369921875000003],[26.168066406250006,-19.53828125000001],[26.241015625000017,-19.5693359375],[26.474609375,-19.748632812500006],[26.67822265625,-19.89277343750001],[26.91669921875001,-19.99013671875001],[27.091796875,-20.05419921875],[27.17822265625,-20.10097656250001],[27.221484375000017,-20.145800781250003],[27.256738281250023,-20.232031250000006],[27.27460937500001,-20.3818359375],[27.28076171875,-20.47871093750001],[27.46894531250001,-20.47480468750001],[27.624609375000006,-20.48359375000001],[27.679296875000006,-20.503027343750006],[27.699609375000023,-20.53066406250001],[27.69482421875,-20.594531250000003],[27.69697265625001,-20.689746093750003],[27.70429687500001,-20.766406250000003],[27.688085937500006,-20.84833984375001],[27.67695312500001,-20.94482421875],[27.66943359375,-21.064257812500003],[27.693457031250006,-21.11103515625001],[27.844140625000023,-21.261523437500003],[27.90742187500001,-21.35908203125001],[27.974609375,-21.50673828125001],[28.014062500000023,-21.55419921875],[28.04560546875001,-21.573046875000003],[28.181640625,-21.58935546875],[28.532031250000017,-21.65126953125001],[28.74775390625001,-21.707617187500006],[28.919335937500023,-21.76601562500001],[28.99072265625,-21.78144531250001],[29.02558593750001,-21.796875],[29.03730468750001,-21.811328125000003],[29.01582031250001,-21.93994140625],[29.023339843750023,-21.981250000000003],[29.042382812500023,-22.018359375000003],[29.07148437500001,-22.047460937500006],[29.106835937500023,-22.065722656250003],[29.237207031250023,-22.07949218750001],[29.315234375000017,-22.15771484375],[29.364843750000006,-22.193945312500006],[29.37744140625,-22.19277343750001],[29.6630859375,-22.146289062500003],[29.90234375,-22.184179687500006],[30.1904296875,-22.291113281250006],[30.46015625000001,-22.32900390625001],[30.71162109375001,-22.2978515625],[30.916113281250006,-22.29072265625001],[31.07343750000001,-22.30781250000001],[31.197265625,-22.34492187500001],[31.287890625000017,-22.40205078125001]]]},"properties":{"featurecla":"Admin-0 country","scalerank":1,"LABELRANK":3,"SOVEREIGNT":"Zimbabwe","SOV_A3":"ZWE","ADM0_DIF":0,"LEVEL":2,"TYPE":"Sovereign country","ADMIN":"Zimbabwe","ADM0_A3":"ZWE","GEOU_DIF":0,"GEOUNIT":"Zimbabwe","GU_A3":"ZWE","SU_DIF":0,"SUBUNIT":"Zimbabwe","SU_A3":"ZWE","BRK_DIFF":0,"NAME":"Zimbabwe","NAME_LONG":"Zimbabwe","BRK_A3":"ZWE","BRK_NAME":"Zimbabwe","BRK_GROUP":"","ABBREV":"Zimb.","POSTAL":"ZW","FORMAL_EN":"Republic of Zimbabwe","FORMAL_FR":"","NAME_CIAWF":"Zimbabwe","NOTE_ADM0":"","NOTE_BRK":"","NAME_SORT":"Zimbabwe","NAME_ALT":"","MAPCOLOR7":1,"MAPCOLOR8":5,"MAPCOLOR9":3,"MAPCOLOR13":9,"POP_EST":13805084,"POP_RANK":14,"GDP_MD_EST":28330,"POP_YEAR":2017,"LASTCENSUS":2002,"GDP_YEAR":2016,"ECONOMY":"5. Emerging region: G20","INCOME_GRP":"5. Low income","WIKIPEDIA":-99,"FIPS_10_":"ZI","ISO_A2":"ZW","ISO_A3":"ZWE","ISO_A3_EH":"ZWE","ISO_N3":"716","UN_A3":"716","WB_A2":"ZW","WB_A3":"ZWE","WOE_ID":23425004,"WOE_ID_EH":23425004,"WOE_NOTE":"Exact WOE match as country","ADM0_A3_IS":"ZWE","ADM0_A3_US":"ZWE","ADM0_A3_UN":-99,"ADM0_A3_WB":-99,"CONTINENT":"Africa","REGION_UN":"Africa","SUBREGION":"Eastern Africa","REGION_WB":"Sub-Saharan Africa","NAME_LEN":8,"LONG_LEN":8,"ABBREV_LEN":5,"TINY":-99,"HOMEPART":1,"MIN_ZOOM":0,"MIN_LABEL":3,"MAX_LABEL":8,"NE_ID":1159321441,"WIKIDATAID":"Q954","NAME_AR":"زيمبابوي","NAME_BN":"জিম্বাবুয়ে","NAME_DE":"Simbabwe","NAME_EN":"Zimbabwe","NAME_ES":"Zimbabue","NAME_FR":"Zimbabwe","NAME_EL":"Ζιμπάμπουε","NAME_HI":"ज़िम्बाब्वे","NAME_HU":"Zimbabwe","NAME_ID":"Zimbabwe","NAME_IT":"Zimbabwe","NAME_JA":"ジンバブエ","NAME_KO":"짐바브웨","NAME_NL":"Zimbabwe","NAME_PL":"Zimbabwe","NAME_PT":"Zimbábue","NAME_RU":"Зимбабве","NAME_SV":"Zimbabwe","NAME_TR":"Zimbabve","NAME_VI":"Zimbabwe","NAME_ZH":"辛巴威"}}, My code: <svg id="mapSVG" width="560"; height="350" style="border: solid 1px black;"></svg> <script src="js/d3.js"></script> <script src="js/d3.min.js"></script> <script type="text/javascript"> //Setting svg width and attributes var svg = d3.select("svg"); var width = +svg.attr("width"); var height = +svg.attr("height"); d3.json("Resources/countries.json").then(function (json) { var projection = d3.geoMercator().fitSize([width, height], json); //Projections var geoPath = d3.geoPath().projection(projection); svg.selectAll("path") .data(json.features) .enter() .append("path") .attr("d", geoPath) .style("fill", "steelblue") }) Problems: The SVG is completely empty. There is no error log in the console and I tried to output the json and it is actually getting the data. When I inspect the svg, the size of the whole svg is 560x350, so I tried to play with the translate and center, but had no luck with it.
#AndrewReid was correct. It was a winding problem and fortunately there is a simple way to fix it using turf.js d3.json(path).then(function (json) { var projection = d3.geoMercator(); var features = json.features; var fixed = features.map(function (feature) { return turf.rewind(feature, { reverse: true }); }) //Projections var geoPath = d3.geoPath().projection(projection); projection.fitSize([width, height], { "type": "FeatureCollection", "features": fixed }) svg.selectAll("path") .data(fixed) .enter() .append("path") .attr("d", geoPath)
Why is my choropleth coming out all the same colour?
This is my first question on here so please bear with. I'm trying to make a choropleth (a map where different sections are coloured in based on some value assigned to them) using d3.js. I'm using the example given at https://www.d3-graph-gallery.com/graph/choropleth_basic.html, but changing the map to one of Scotland and changing the values to population density. When I run it, I get a map but it's all coloured in the same shade of blue. I've tried changing the domain of colorScale but to no avail. This is what I've got at the minute: // The svg var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); // Map and projection var path = d3.geoPath(); var projection = d3.geoNaturalEarth() .scale(20 * width / Math.PI) .translate([width / 2 + 150, height / 2 + 2500]); // Data and color scale var data = d3.map(); var colorScale = d3.scaleThreshold() .domain([0, 600]) .range(d3.schemeBlues[7]); // Load external data and boot d3.queue() .defer(d3.json, "https://raw.githubusercontent.com/squirrel-star/scotland/main/geojsonscotlandladjson.geojson") .defer(d3.csv, "https://raw.githubusercontent.com/squirrel-star/scotland/main/scotlanddensitywithid.csv", function(d) { data.set(d.code, +d.density); }) .await(ready); function ready(error, topo) { console.log(data); // Draw the map svg.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(d.id) || 0; return colorScale(d.total); }); } <script src="https://d3js.org/d3.v4.js"></script> <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> <script src="https://d3js.org/d3-geo-projection.v2.min.js"></script> <svg id="my_dataviz" width="400" height="400"></svg> Any suggestions for fixing it would be greatly appreciated. Thank you!
I think you may have misread the documentation for d3.scaleThreshold, because it says you need to have N values in your domain if you have N + 1 values in your range. In your case, that makes N = 6. Also, d.id didn't exist. I used d.properties.LAD13NM instead, because that field contained the name of the relevant county. Finally, there was no need to use a map, since you were only using it as an object of some sorts, so I just replaced it with a regular object. // The svg var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); // Map and projection var path = d3.geoPath(); var projection = d3.geoNaturalEarth() .scale(20 * width / Math.PI) .translate([width / 2 + 150, height / 2 + 2500]); // Data and color scale var data = {}; var colorScale = d3.scaleThreshold() .domain([100, 200, 300, 400, 500, 600]) .range(d3.schemeBlues[7]); // Load external data and boot d3.queue() .defer(d3.json, "https://raw.githubusercontent.com/squirrel-star/scotland/main/geojsonscotlandladjson.geojson") .defer(d3.csv, "https://raw.githubusercontent.com/squirrel-star/scotland/main/scotlanddensitywithid.csv", function(d) { data[d.code] = +d.density; }) .await(ready); function ready(error, topo) { // Draw the map svg.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[d.properties.LAD13NM] || 0; return colorScale(d.total); }); } <script src="https://d3js.org/d3.v4.js"></script> <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> <script src="https://d3js.org/d3-geo-projection.v2.min.js"></script> <svg id="my_dataviz" width="400" height="400"></svg>
D3.js Circles on Map
I am very new to coding and am trying to learn D3. I have map of France which I am able to make appear in the browser. However, I am trying to display circles on the map based on a csv file. I am not sure what I am doing wrong with the function... Any help/direction would be great. Here is a Cloud9 of the code and files... https://ide.c9.io/santiallende/d3-map-bubbles-france
I won't sugarcoat, your code's a mess. You define and append 4 different svg elements to the body and you create 3 different projections. All of it is unnecessary. Just go through and remove all the redundancies. //Width and height var w = 800; var h = 350; var canvas = d3.select("body").append("svg") .attr("width", w) .attr("height", h) d3.json("france.json", function(data) { var group = canvas.selectAll("g") .data(data.features) .enter() .append("g") //Define map projection var projection = d3.geo.mercator() .translate([400, 1200]) .scale([1100]); //Define path generator var path = d3.geo.path() .projection(projection); var areas = group.append("path") .attr("d", path) .attr("class", "area") .attr("fill", "steelblue"); //Load in cities data d3.csv("wineregions.csv", function(data) { canvas.selectAll("circle") .data(data) .enter() .append("circle") .attr("cx", function(d) { return projection([d.lon, d.lat])[0]; }) .attr("cy", function(d) { return projection([d.lon, d.lat])[1]; }) .attr("r", 5) .style("fill", "yellow") .style("opacity", 0.75); }); }); Fixed code here.
How to control the order of the layers on a map in d3js
I have a simple question about making maps with d3js. I want to make a map with two layers. One layer is the contour of the map (geoJson) and the other layer contains the streets (topoJson). My problem is that streets layer always is loaded in front of the layer of contour, no matter which one is written before in the code. I would like the opposite situation: the contour layer in front of the streets. I think this problem happen because both request are asynchronous and the contour layer is loaded before because is the lightest. Here is the code... //Width and height var w = 900; var h = 500; //Define map projection var projection = d3.geo.transverseMercator() .center([2.5, -34.65]) .rotate([61.5, 0]) .scale((h * 750.5) / 3) .translate([(w/2), (h/2)]); //Define path generator var path = d3.geo.path() .projection(projection); //Create SVG element var svg = d3.select("body") .append("svg") .attr("width", w) .attr("height", h); //Load in TopoJSON data d3.json("streets.json", function(error, topology) { svg.selectAll("path") .data(topojson.feature(topology, topology.objects.layer1).features) .enter() .append("path") .attr("d", path) .style("fill", "white") .style("stroke", "#cccccc"); }); //Load in GeoJSON data d3.json("contour.geojson", function(json) { //Bind data and create one path per GeoJSON feature svg.selectAll("path") .data(json.features) .enter() .append("path") .attr("d", path) .style("fill","white") .style("stroke","black") .style("stroke-width",4); }); Is it possible load first the layer of streets, wait until the streets were drawn and then load the layer of contour? Thanks in advance.
I would create two separate g elements for the layers in the beginning. This way you can control their order: var countourG = svg.append("g"), streetG = svg.append("g"); d3.json("streets.json", function(error, topology) { streetG.selectAll("path")... }); d3.json("contour.json", function(error, topology) { contourG.selectAll("path")... });