Public
Edited
Apr 18
Importers
10 stars
Insert cell
Insert cell
Plot.plot({
x: {
domain: [0, 20],
clamp: true,
tickFormat: d => (d == 0 ? '0' : d + ' years old'),
label: null
},
y: {
axis: null
},
color: { scheme: 'ylorrd' },
facet: {
data,
y: 'breed',
marginRight: 160
},
fy: {
axis: 'right',
paddingInner: -0.5,
domain: d3.sort(meanAges, d => d[1]).map(d => d[0]),
label: null
},
height: meanAges.size * 40,
marginTop: 0,
marginLeft: 5,
marks: [
Plot.areaY(
data,
Plot.normalizeY({
x: 'age',
y: 'count',
fill: d => meanAges.get(d.breed),
curve: 'monotone-x',
basis: d3.max
})
),
Plot.lineY(
data,
Plot.normalizeY({
x: 'age',
y: 'count',
stroke: '#ccc',
strokeWidth: 1,
curve: 'monotone-x',
basis: d3.max
})
)
]
})
Insert cell
meanAges = d3.rollup(
data,
dogs => {
let total = d3.sum(dogs, d => d.count);
let meanAge = d3.sum(dogs, d => (d.age * d.count) / total);
return meanAge;
},
d => d.breed
)
Insert cell
data = FileAttachment("breed_ages.json")
.json()
.then(data =>
data.flatMap(([breed, ages]) => {
// The data for some breeds contains missing age bins, implicitly indicating
// zero values. This can cause misplotting when used with area marks, so we
// add explicit zero bins for missing ages.
let map = d3.index(ages, d => d[0]);
let max = d3.max(ages, d => d[0]);
for (let i = 0; i < max; i++) if (!map.has(i)) map.set(i, [i, 0]);
return Array.from(map.values(), ([age, count]) => ({
breed,
age,
count
})).sort((a, b) => d3.ascending(a.age, b.age));
})
)
Insert cell
d3 = import("d3@7")
Insert cell
Plot = require("@observablehq/plot@0.5")
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