Public
Edited
May 29, 2023
Insert cell
Insert cell
viewof year = slider({
min: 2005,
max: 2020,
value: 2020,
step: 1,
title: "Year"
})
Insert cell
legend({
color: d3.scaleSequential([0, 10], d3.interpolateSpectral),
title: `World Happiness by Country in ${year}`
})
Insert cell
{ const selectedCountry = vl.selectSingle('select')
.fields(`properties.${year}`)
.on('click')
.clear('dblclick')

const choropleth = vl
.markGeoshape({ stroke: 'white', tooltip: {content: 'data'} })
.data(choroplethData)
.params(selectedCountry)
.title({text: "Happiness by Country", subtitle: "Click to select a country | Use the slider to change year | Double click to deselect"})

.encode(
vl
.color().if(selectedCountry, vl.fieldQ(`properties.${year}`)).value("grey"),
vl.tooltip([
{
field: 'properties["Country"]',
type: 'nominal',
title: 'Country'
},
{
field: `properties.${year}`,
type: 'quantitative',
title: 'Happiness'
}
])
)
.project(
vl
.projection("naturalEarth1")
.translate([450, 300])
.rotate(0)
.scale(200)
)
.width(width - 10)
.height(500)
.config({
view: { stroke: null }
})
const countryBarPlot = vl.markBar({align: 'left', dx: 3})
.data(barChartData)
.transform(vl.filter(selectedCountry))
.encode(
vl.x().fieldQ('Year'),
vl.y().fieldQ('Happiness')
).width(width - 300);

return vl.vconcat(choropleth, countryBarPlot).render()
}
Insert cell
barChartData = FileAttachment("world_happiness_report_updated.csv")
Insert cell
choroplethData = {
const [worldTopo, worldHappiness, countryCodes] = await Promise.all([
d3.json('https://unpkg.com/world-atlas@1/world/110m.json'),
FileAttachment("world_happiness_chloropeth.csv").csv({ typed: true }),
d3.csv(
"https://gist.githubusercontent.com/jashkenas/59c7c820265537b941251dabe33a8413/raw/7ccd0d24ef50b3152ce848e7c3f9ce21a0d75af6/country-codes.csv"
)
]);
const worldGeoJSON = topojson.feature(worldTopo, "countries");
return worldGeoJSON.features.map(countryFeature => {
const iso3166Code = countryFeature.id;
// look up alpha 3 code, if not found treat as null
const alpha3 = countryCodes.find(
codes => codes['country-code'] == iso3166Code
)?.['alpha-3'];
const countryHappinessData = worldHappiness.find(
country => country['alpha3'] == alpha3
);
countryFeature.properties = countryHappinessData;
return countryFeature;
});
}
Insert cell
import {Choropleth} from "@d3/choropleth"
Insert cell
topojson = require("topojson-client")
Insert cell
import {vl as api} from "@vega/vega-lite-api"
Insert cell
import {concious_analytics} from "ff90685a875a43ac"
Insert cell
import {addExtendedProjections, extendedProjections} from "@vega/vega-utilities"
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
import {legend} from "@d3/color-legend"
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