Published
Edited
Nov 11, 2021
1 star
Insert cell
# Map challenge
Insert cell
## Source data
Insert cell
Insert cell
cartographers_2019 = d3.csv(
"https://raw.githubusercontent.com/dakvid/30DayMapChallenge/master/data/cartographers.csv",
d => ({ country: d.location, ...d, year: 2019 })
)
Insert cell
days_2020 = d3.csv("https://raw.githubusercontent.com/dakvid/30DayMapChallenge2020/main/data/day_matrix_for_heatmap.csv")
Insert cell
## Merge cartographers
Insert cell
rename = new Map([
["UK", "United Kingdom"],
["LUK", "United Kingdom"],
["USA", "United States of America"],
["Oslo, Norway", "Norway"],
])
Insert cell
cartographers = [
...cartographers_2019,
...cartographers_2020
].map(d => ({ countryName: rename.get(d.country) || d.country, ...d }))
Insert cell
Plot.plot({
width : 300,
marks: [
Plot.barY(cartographers, Plot.groupX({y: "count"}, {x: "year"})),
Plot.ruleY([0])
]
})
Insert cell
## Where are cartographers ?
Insert cell
locatedCartographers = cartographers.filter(({ country }) => country !== "")
Insert cell
countryList = cartographers.map(({ country }) => country)
Insert cell
countryRollup = d3.rollups(cartographers, v => v.length, d => d.countryName, d => d.year)
Insert cell
Insert cell
Insert cell
countryCount = countryRollup
.map(([ country, [count19, count20]]) => ({ country, count19, count20 })) // to handle undefined values
.map(({ country, count19, count20 }) => ({
country,
count2019: getcount(count19),
count2020: getcount(count20),
}))
Insert cell
import {serialize} from "@palewire/saving-csv"
Insert cell
DOM.download(serialize(countryCount), 'countryCount.csv', "Download CSV")
Insert cell
Choropleth(countryCount, {
id: d => d.country, // country name, e.g. Zimbabwe
value: d => d.count2019,
range: d3.interpolateYlGnBu,
domain: countryCountRange,
features: countries,
featureId: d => d.properties.name,
borders: countrymesh,
projection: d3.geoEqualEarth(),
})
Insert cell
chart = Choropleth(countryCount, {
id: d => d.country, // country name, e.g. Zimbabwe
value: d => d.count2020, // health-adjusted life expectancy
range: d3.interpolateYlGnBu,
features: countries,
featureId: d => d.properties.name, // i.e., not ISO 3166-1 numeric
borders: countrymesh,
projection: d3.geoEqualEarth(),
})
Insert cell
import {countries} from "@d3/world-choropleth"
Insert cell
import {countrymesh} from "@d3/world-choropleth"
Insert cell
### Cartographers that are coming back
Insert cell
cartographers_2019_handles = cartographers_2019.map(({ handle }) => handle)
Insert cell
serailcartographers = cartographers
.filter(({ year }) => year === 2020)
.map(c => ({
serial : cartographers_2019_handles.includes(c.handle),
isNew : !cartographers_2019_handles.includes(c.handle),
...c }))
Insert cell
d3.rollups(
serailcartographers.filter(({ isNew }) => isNew),
v => v.length, d => d.countryName
)
Insert cell
domain = [true, false]
Insert cell
textDomain = ["Serial cartographer (here in 2019)", "New in 2020"]
Insert cell
colorscale = ['#03045e', '#0077b6']
Insert cell
Insert cell
Insert cell
## Imports
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
import {Choropleth} from "@d3/choropleth"
Insert cell
## Sources
https://observablehq.com/@d3/world-choropleth
Insert cell
world = FileAttachment("countries-50m.json").json()
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