Public
Edited
Nov 6, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chartElem = Plot.plot({
// size and margins
height: 540,
width: 600,
margin: 0,

projection: {
type: "azimuthal-equal-area",
domain: europeGeo,
inset: 16
},

marks: [
// background (oceans and lakes)
Plot.frame({ fill: "#f7fbfd" }),

// base map
Plot.geo(worldGeo2, {
fill: "#fff",
strokeWidth: 0.5,
stroke: "#cdcdcd"
}),

// data map
Plot.geo(europeGeo, {
fill: (d) =>
catDogMap.has(d.properties.NAME)
? catDogMap.get(d.properties.NAME).color
: "url(#diagonalHatch)",
fillOpacity: 0.8,
stroke: (d) =>
countryHighlight.includes(d.properties.NAME) ? "#222" : "#535353",
strokeWidth: (d) =>
countryHighlight.includes(d.properties.NAME) ? 1 : 0.5,
strokeOpacity: (d) => (catDogMap.has(d.properties.NAME) ? 1 : 0.2)
}),

// legend
(a, b, c, layout) =>
svg`
<g transform="translate(${layout.width - 106 - 48},${48 - 16})">
${Plot.plot({
height: 120,
width: 120,
margin: 0,
inset: 17,
marks: [
Plot.rect(d3.cross([0, 1, 2], [0, 1, 2]), {
x: ([a, b]) => a,
y: ([a, b]) => b,
interval: 1,
fill: ([a, b]) => colors[a + b * 3],
inset: -1,
stroke: "#222",
strokeWidth: 0.5
}),

Plot.text(["More dogs →"], {
fontWeight: "bold",
fontSize: 12,
x: 0,
y: 0,
rotate: 0,
textAnchor: "middle",
dx: 60 - 16,
dy: 10
}),

Plot.text(["More cats →"], {
fontWeight: "bold",
fontSize: 12,
x: 0,
y: 0,
rotate: 0,
textAnchor: "middle",
rotate: -90,
dx: -10,
dy: -60 + 16
})
]
})}
</g>`
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
europe 2022 cat dog@2.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
catDogMap = {
// adapted from https://observablehq.com/@d3/bivariate-choropleth

const n = Math.sqrt(colors.length);

const x = d3.scaleQuantile(
Array.from(europe2022CatDog, (d) => d.cat).concat(0),
d3.range(n)
);

const y = d3.scaleQuantile(
Array.from(europe2022CatDog, (d) => d.dog).concat(0),
d3.range(n)
);

const color = (value) => {
if (!value) return "#ccc";
const { cat, dog } = value;
return colors[y(dog) + x(cat) * n];
};

const result = new Map();
europe2022CatDog
.map((d) => ({ ...d, color: color(d) }))
.forEach((d) => result.set(d.country, d));

return result;
}
Insert cell
Insert cell
Select a data source…
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
europeGeo = {
const geo = await FileAttachment("europe-geo.json").json();
let topo = topojson.feature(geo, geo.objects.europe);

// transform data
topo.features.forEach(
(d) => (d.properties.NAME = d.properties.NAME.replace(/[^a-zA-Z ]/g, ""))
);

return {
type: "FeatureCollection",
features: topo.features.filter(
(f) => countries.findIndex((c) => c === f.properties.NAME) > -1
)
};
}
Insert cell
averages = {
return {
dog:
europe2022CatDog.reduce((pre, cur) => pre + cur.dog, 0) /
europe2022CatDog.length /
100,
cat:
europe2022CatDog.reduce((pre, cur) => pre + cur.cat, 0) /
europe2022CatDog.length /
100
};
}
Insert cell
percentFormat = new Intl.NumberFormat("en-US", {
style: "percent",
minimumFractionDigits: 1,
maximumFractionDigits: 1
})
Insert cell
worldGeo2 = {
const geo = await FileAttachment("ne_10m_admin_0_countries (1).json").json();
return topojson.feature(geo, geo.objects.ne_10m_admin_0_countries);
}
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