Published
Edited
Sep 21, 2021
35 forks
Importers
35 stars
Insert cell
Insert cell
Insert cell
Insert cell
data = (await FileAttachment("cbo-targets-actuals.csv").csv()).map(autoTypeExcel)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
TargetsVsActuals = (data, {title, x, target, actual, ...options} = {}) =>
Plot.plot({
height: 250,
x: {tickFormat: dateFormat, label: null},
y: {label: title},
color: {
range: ["#b44646", "steelblue"],
domain: [-1e-6, 1e-6],
clamp: true
},
...options,
marks: [
HollowBarY(data, {x, target, actual}), // includes blue bar, outline, and label
Plot.ruleY([0]) // baseline
]
})
Insert cell
Insert cell
HollowBarY = (data, {x, target, actual} = {}) => {
// Calculate percentage
data = data.map(d => ({...d, percent: maybeAccessor(actual)(d) / maybeAccessor(target)(d)}))
return [
// Blue bar for actuals
Plot.barY(data, {x, y: actual, fill: actual, insetLeft: 0.5, insetRight: 0.5}),

// Hollow bar for targets
Plot.barY(data, {x, y: target, stroke: "black", fill: "none"}),

// Percentage text, below and white if miss
Plot.text(data.filter(d => d.percent < 1), {
x,
y: actual,
text: d => pct(d.percent),
fill: "white",
dy: 12,
}),

// Percentage text, above and black if hit
Plot.text(data.filter(d => d.percent > 1), {
x,
y: actual,
text: d => pct(d.percent),
dy: -4
})
]
}
Insert cell
maybeAccessor = value => typeof value === "string" ? d => d[value] : value;
Insert cell
pct = d3.format(".0%")
Insert cell
import {Table} from "@observablehq/table-validator"
Insert cell
import {dateFormat, autoTypeExcel} from "@observablehq/cash-flow"
Insert cell
import {toc} from "@observablehq/templates-table-of-instructions"
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