Published unlisted
Edited
Feb 28, 2022
Insert cell
Insert cell
Insert cell
Plot.plot({
width,
y: {
label: "↑ Daily downloads",
tickFormat: "s"
},
marks: [
Plot.areaY(data, {
x: "date",
y: "value",
fill: "steelblue",
curve: "step"
}),
Plot.ruleY([0])
]
})
Insert cell
data = seriesX(data0, d3.utcDay)
Insert cell
// this could be a mark option for Plot.areaY and Plot.lineY; maybeInterval(series)
function seriesX(data0, interval) {
const data = [];
let prev;
for (const { date: x, value: y } of d3.sort(data0, (d) => d.date)) {
if (prev !== undefined) {
if (interval.floor(x) > prev) {
data.push({ date: prev, value: 0 });
if (interval.offset(x, -1) > prev) {
data.push({ date: interval.offset(x, -1), value: 0 });
}
}
}
prev = interval.offset(x);
data.push({ date: x, value: y });
}
return data;
}
Insert cell
data0 = {
const data = Object.assign([], { y: "daily downloads" });
const min = new Date(2015, 0, 1);
const max = d3.utcDay(new Date());
let start = max;
let end;
while (start > min) {
end = start;
start = d3.utcDay.offset(start, -365);
if (start < min) start = min;
try {
const batch = await d3.json(
`https://api.npmjs.org/downloads/range/${formatDate(
start
)}:${formatDate(d3.timeDay.offset(end, -1))}${
name ? `/${encodeURIComponent(name)}` : ``
}`
);
for (const { downloads: value, day: date } of batch.downloads.reverse()) {
if (value > 0) {
data.push({ date: new Date(date), value });
}
}
yield data;
} catch {
return;
}
}
}
Insert cell
formatDate = d3.utcFormat("%Y-%m-%d")
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