Public
Edited
Sep 23, 2024
2 forks
34 stars
Insert cell
Insert cell
Insert cell
chart = {
const L = legend();
const color = L.scale("color");

const index = new Map(data.map(({ county, ...rest }) => [county, rest]));

return Plot.plot({
width: 975,
height: 610,
projection: "identity",
color,
marks: [
Plot.geo(
topojson.feature(us, us.objects.counties),
Plot.centroid({
stroke: "white",
strokeWidth: 0.125,
fill: (d) => bivariateClass(index.get(d.id)),
title: (d) => {
const name = `${d.properties.name}, ${
states.get(d.id.slice(0, 2)).name
}`;
const value = index.get(d.id);
if (!value || (isNaN(value.diabetes) && isNaN(value.obesity)))
return `${name}\nno data`;
const [dc, oc] = bivariateClass(value);
return `${name}\n${
isNaN(value.diabetes) ? "No Data" : value.diabetes
}% Diabetes${label(dc)}\n${
isNaN(value.obesity) ? "No Data" : value.obesity
}% Obesity${label(oc)}`;
},
tip: true
})
),
Plot.geo(
topojson.mesh(us, us.objects.states, (a, b) => a !== b),
{ stroke: "white" }
),
() => svg`<g transform="translate(835,410)">${L}`
],
style: "overflow: visible;"
});
}
Insert cell
Insert cell
legend = () =>
Plot.plot({
color: {
range: scheme,
transform: ([a, b]) => 3 * a + b,
unknown: "#ccc" // See Valdez-Cordova, Alaska
},
axis: null,
margin: 0,
inset: 18,
width: 106,
height: 106,
style: "overflow: visible;", // for the tip
marks: [
Plot.dot(d3.cross([0, 1, 2], [0, 1, 2]), {
x: ([a, b]) => b - a,
y: ([a, b]) => b + a,
symbol: "square",
rotate: 45,
r: 14,
fill: (d) => d,
title: ([a, b]) => `Diabetes${label(a)}\nObesity${label(b)}`,
tip: true
}),
Plot.text(["Obesity →"], {
frameAnchor: "right",
fontWeight: "bold",
rotate: -45,
dy: 10
}),
Plot.text(["← Diabetes"], {
frameAnchor: "left",
fontWeight: "bold",
rotate: 45,
dy: 10
})
]
})
Insert cell
Insert cell
labels = ["low", "", "high"]
Insert cell
label = i => labels[i] ? ` (${labels[i]})` : ""
Insert cell
Insert cell
data = FileAttachment("cdc_diabetes_obesity_2020.csv").csv()
.then((data) => {
data.forEach((d) => {
d.obesity = +d.obesity; // type as numeric
d.diabetes = +d.diabetes;
});
return data;
})
Insert cell
Insert cell
diabetes = Plot.plot({
width: 640,
height: 330,
x: {line: true},
color: { type: "quantile", range: [0, 1, 2].map((i) => scheme[3 * i]) },
marks: [
Plot.dotX(
data,
Plot.dodgeY({
x: "diabetes",
fill: "diabetes",
r: 1.2,
padding: 0.2,
})
)
]
})
Insert cell
Insert cell
obesity = Plot.plot({
width: 640,
height: 170,
x: {line: true},
color: { type: "quantile", range: [0, 1, 2].map((i) => scheme[i]) },
marks: [
Plot.dotX(
data,
Plot.dodgeY({
x: "obesity",
fill: "obesity",
r: 1.2,
padding: 0.2,
})
)
]
})
Insert cell
Insert cell
bivariateClass = {
const d = diabetes.scale("color").domain; // thresholds for diabetes
const o = obesity.scale("color").domain; // thresholds for obesity
return (value) => {
const { diabetes: a, obesity: b } = value;
return [
isNaN(a) ? a : +(a > d[0]) + (a > d[1]),
isNaN(b) ? b : +(b > o[0]) + (b > o[1])
];
};
}
Insert cell
Insert cell
diabetes_thresholds = d3.scaleQuantile(data.map(d => d.diabetes), [0, 1, 2]).quantiles()
Insert cell
obesity_thresholds = d3.scaleQuantile(data.map(d => d.obesity), [0, 1, 2]).quantiles()
Insert cell
Insert cell
Plot.plot({
width: 450,
inset: 10,
color: legend().scale("color"),
marks: [
Plot.linearRegressionY(data, {
x: "diabetes",
y: "obesity",
opacity: 0.5
}),
Plot.dot(data, {
x: "diabetes",
y: "obesity",
fill: bivariateClass,
channels: { county: "county" },
tip: true,
r: 1.4
}),
Plot.text(
data,
Plot.groupZ(
{ text: "count", x: "mean", y: "mean" },
{
fontSize: 14,
stroke: "white",
strokeWidth: 8,
fill: "currentColor",
x: "diabetes",
y: "obesity",
z: (d) => bivariateClass(d).toString()
}
)
),
["p33", "p67"].map((pxx) => [
Plot.ruleX(
data,
Plot.groupZ(
{ x: pxx },
{ x: "diabetes", strokeDasharray: 4, strokeOpacity: 0.4 }
)
),
Plot.ruleY(
data,
Plot.groupZ(
{ y: pxx },
{ y: "obesity", strokeDasharray: 4, strokeOpacity: 0.4 }
)
)
])
]
})
Insert cell
Insert cell
schemes = [
{
name: "RdBu",
colors: [
"#e8e8e8", "#e4acac", "#c85a5a",
"#b0d5df", "#ad9ea5", "#985356",
"#64acbe", "#627f8c", "#574249"
]
},
{
name: "BuPu",
colors: [
"#e8e8e8", "#ace4e4", "#5ac8c8",
"#dfb0d6", "#a5add3", "#5698b9",
"#be64ac", "#8c62aa", "#3b4994"
]
},
{
name: "GnBu",
colors: [
"#e8e8e8", "#b5c0da", "#6c83b5",
"#b8d6be", "#90b2b3", "#567994",
"#73ae80", "#5a9178", "#2a5a5b"
]
},
{
name: "PuOr",
colors: [
"#e8e8e8", "#e4d9ac", "#c8b35a",
"#cbb8d7", "#c8ada0", "#af8e53",
"#9972af", "#976b82", "#804d36"
]
}
]
Insert cell
Insert cell
us = FileAttachment("counties-albers-10m.json").json()
Insert cell
states = new Map(us.objects.states.geometries.map(d => [d.id, d.properties]))
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