Public
Edited
Apr 5, 2022
1 fork
1 star
Insert cell
Insert cell
<svg width="1000" height="500">
<g id="countries"></g>
<g id="countrysparklines"></g>
</svg>
Insert cell
map = d3.select(mapContainer)
Insert cell
import {getMapData, drawMapLayer} with {projection} from "@emfielduva/dvlib_maps"
Insert cell
world = getMapData("world110m")
Insert cell
mapLayers = {
let mapLayers = [];
mapLayers["countries"] = drawMapLayer(map,"countries",world.features,world.idField);
return mapLayers;
}
Insert cell
<style>
#countries path {fill: #fefefe; stroke: #efefef;}
#countrysparklines line {stroke: #777; stroke-width: 0.5}
#countrysparklines g {opacity: 0.5;}
#countrysparklines g:hover {opacity: 1;}
</style>
Insert cell
Insert cell
Insert cell
gdp = FileAttachment("world-gdp-growth.csv").csv()
Insert cell
import {toNum} from "@emfielduva/dvlib"
Insert cell
Insert cell
First we need to get the **centroid points** of the countries to put the circles on.
Insert cell
projection = d3.geoMercator()
Insert cell
import {geoCentroids} with {projection} from "@emfielduva/dvlib_maps"
Insert cell
countryCentroids = {
let centroids = geoCentroids(world.features, "id");
return d3.index(centroids, d => d["name"]); // return it as an indexed map by country "name". It's just easier to access this way.
}
Insert cell
Insert cell
getCoord = (countryCode) => {
let coord = "";
// in matching across datasets, they may not all have a match. This will test first and return only when it does
if (typeof(countryCentroids.get(countryCode)) !== "undefined") {
coord = countryCentroids.get(countryCode).coord;
}
return coord;
}
Insert cell
countryGroups = map.select("#countrysparklines")
.selectAll(".countrySparkline")
.data(gdp)
.join("g")
//.attr("x", d => projection(getCoord(d["Country Code"]))[0])
//.attr("y", d => projection(getCoord(d["Country Code"]))[1])
.attr("transform", d => "translate("
+ projection(getCoord(d["Country Code"]))[0] + " "
+ projection(getCoord(d["Country Code"]))[1]
+ ")")
.attr("id", d => "sl_"+d["Country Code"]) // to name each one by it's name, prepending "sl_" to the name.
.classed("countrySparkline", true);
Insert cell
Insert cell
scaleX = d3.scaleLinear().domain([1967,2011]).range([2,28]);
Insert cell
scaleY = d3.scaleLinear().domain([-20,20]).range([20,0]);
Insert cell
Insert cell
gdp_pivot = FileAttachment("world-gdp-growth_pivot.csv").csv()
Insert cell
countryGroups.each((d,i,nodes) => {
let thisCountryCode = d["Country Code"];
let spark = d3.select(nodes[i]).selectAll("line")
.data(gdp_pivot)
.join("line")
.attr("x1", d=>scaleX(+d.Year)).attr("y1",scaleY(0))
.attr("x2", d=>scaleX(+d.Year)).attr("y2",d=>scaleY(+d[thisCountryCode]))
.style("stroke", d => +d[thisCountryCode] > 0 ? "green" : "red");
})
Insert cell
Insert cell
mapLayers["countries"].style("visibility", 'hidden')
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more