Unlisted
Edited
Oct 14, 2024
Insert cell
Insert cell
Insert cell
Plot.plot({
width: 928,
height: 500,
x: { label: null },
y: { label: "PERCENT", tickFormat: "s", tickSpacing: 50 },
color: {
scheme: "Spectral",
legend: "ramp",
width: 340,
label: "Age (years)"
},
marks: [
Plot.barY(tidy, {
filter: (d) => d.age !== "40-49",
...Plot.stackY({
order: (a, b) => (a === "40-49" ? 1 : 0),
x: "state",

y: "population",
fill: "age",
sort: { color: null, x: "-y" },
offset: "normalize",
channels: {
customY: {
label: "Percent",
value: "population"
}
},
tip: {
// Display custom values, hide the auto generated values
format: {
customY: true
}
}
})
})
]
})
Insert cell
Trying a custom tip mark based on [this question](https://talk.observablehq.com/t/pointer-transforms-with-px-py-on-stacked-bar-charts/8302/6), not quite right.
Insert cell
Plot.plot({
width: 928,
height: 500,
x: { label: null },
y: { tickFormat: "s", tickSpacing: 50 },
color: {
scheme: "Spectral",
legend: "ramp",
width: 340,
label: "Age (years)"
},
marks: [
Plot.barY(tidy, {
x: "state",
y: "population",
fill: "age",
sort: { color: null, x: "-y" },
offset: "normalize"
}),
Plot.tip(
tidy,
Plot.pointer(
renameXYPxPy(
Plot.stackY({
x: "state",
y: "population",
fill: "age",
sort: { color: null, x: "-y" },
offset: "normalize",
channels: {
customY: {
label: "Percent",
value: (d) => {
// The value of d has the data values before normalization
console.log(d);
return d.population;
}
}
},
tip: {
// Display custom values, hide the auto generated values
format: {
customY: true
}
}
})
)
)
)
]
})
Insert cell
function renameXYPxPy({ x, y, ...options }) {
return { ...options, px: x, py: y };
}
Insert cell
population = FileAttachment("us-population-state-age.csv").csv({typed: true})
Insert cell
Insert cell
tidy = population.columns.slice(1).flatMap((age) => population.map(d => ({state: d.name, age, population: d[age]})))
Insert cell
Plot.barY(
tidy,
Plot.normalizeY("sum", {
x: "state",
y: "population",
z: "state", // the series for normalizeY
fill: "age",
sort: { color: null, x: "-y" },
offset: "normalize", // stack normalization (based on *x*)
tip: {
channels: {
population: { value: "population", label: "Absolute population" } // 👈
}
}
})
).plot({ y: { label: "Relative population (%)", percent: true } }) // 👈
Insert cell
Plot.plot({
width: 928,
height: 500,
x: { label: null },
y: { label: "PERCENT", tickFormat: "s", tickSpacing: 50 },
color: {
scheme: "Spectral",
legend: "ramp",
width: 340,
label: "Age (years)"
},
marks: [
Plot.barY(
tidy,
...Plot.stackY({
x: "state",
y: "population",
fill: "age",
sort: { color: null, x: "-y" },
offset: "normalize"
})
),
Plot.tip(
tidy,
Plot.pointer(
Plot.stackY({
x: "state",
y: "population",
fill: "age",
sort: { color: null, x: "-y" },
offset: "normalize"
})
)
)
]
})
Insert cell
render(index, scales, values, dimensions, context, next) {
const g = next(index, scales, values, dimensions, context);
d3.select(g)
.selectAll("circle")
.style("opacity", 0)
.transition()
.delay(() => Math.random() * 5000)
.style("opacity", 1);
return g;
}
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