Public
Edited
Feb 16, 2023
12 forks
Importers
28 stars
Insert cell
Insert cell
Plot.plot({
y: {
domain: [15, 87],
ticks: 7,
grid: true,
label: "↑ temperature (°F)"
},
x: {
inset: 4
},
marks: [
differenceY(data, {x: "date", y1: "San Francisco", y2: "New York", curve: "step", fill: orange}),
differenceY(data, {x: "date", y1: "New York", y2: "San Francisco", curve: "step", fill: blue}),
Plot.line(data, {x: "date", y: "New York", curve: "step"}),
Plot.text(data, Plot.selectMaxY({
x: "date",
y: "New York",
text: () => "New York",
dy: -5
})),
Plot.text(data, {
...Plot.selectMinY({
x: "date",
y: d => d["San Francisco"] - d["New York"]
}),
y: "San Francisco",
text: () => "San Francisco",
dy: 10
}),
Plot.text(data, Plot.selectMinY({
x: "date",
y: "New York",
text: () => "New York",
dy: 10
})),
Plot.text(data, {
...Plot.selectMaxY({
x: "date",
y: d => d["San Francisco"] - d["New York"],
text: () => "San Francisco"
}),
y: "San Francisco",
dy: -20
}),
],
width,
height: 450
})
Insert cell
data = FileAttachment("weather.tsv").tsv({typed: true}).then(l => l.map(d => ({...d, date: d3.timeParse("%Y%m%d")(`${d.date}`)})))
Insert cell
blue = d3.schemeRdYlBu[3][2]
Insert cell
orange = d3.schemeRdYlBu[3][0]
Insert cell
Insert cell
differenceY = (data, options) => {
class DifferenceY extends Plot.Area {
constructor(data, {x, y1, y2, ...options} = {}) {
y1 = maybeZero(y1);
y2 = maybeZero(y2);
super(data, {...options, x1: x, x2: undefined, y1, y2});
}
render(I, scales, {x1: X, y1: Y1, y2: Y2 = Y1}, {width}) {
const g = super.render(...arguments);
const uid = DOM.uid();
const line = d3.line().x(i => X[i]).y(i => Y1[i]).curve(this.curve);
d3.select(g)
.style("clip-path", uid)
.append("defs")
.append("clipPath")
.attr("id", uid.id)
.append("path")
.attr("d", `
${line(I)}
L${width},${Y1[I[I.length-1]]} L${width},0 L0,0 M${width},${Y1[I[0]]} Z`
);
return g;
}
}

return new DifferenceY(data, options);
}
Insert cell
Plot.plot({
marginLeft: 80,
x: {
domain: [15, 87],
ticks: 7,
grid: true,
label: "temperature (°F) →"
},
y: {
inset: 4
},
marks: [
differenceX(data, {y: "date", x1: "San Francisco", x2: "New York", curve: "step", fill: orange}),
differenceX(data, {y: "date", x1: "New York", x2: "San Francisco", curve: "step", fill: blue}),
Plot.line(data, {y: "date", x: "New York", curve: "step"})
],
width: 300,
height: 600
})
Insert cell
differenceX = (data, options) => {
class DifferenceX extends Plot.Area {
constructor(data, {y, x1, x2, ...options} = {}) {
x1 = maybeZero(x1);
x2 = maybeZero(x2);
super(data, {...options, x1, x2, y1: y, y2: undefined});
}
render(I, scales, {x1: X1, y1: Y, x2: X2}, {height}) {
const g = super.render(...arguments);
const uid = DOM.uid();
const line = d3.line().x(i => X2[i]).y(i => Y[i]).curve(this.curve);
d3.select(g)
.style("clip-path", uid)
.append("defs")
.append("clipPath")
.attr("id", uid.id)
.append("path")
.attr("d", `
${line(I)}
L${X2[I[I.length-1]]},0 L0,0 L0,${height} M${X2[I[0]]},${height} Z`
);
return g;
}
}
return new DifferenceX(data, options);
}
Insert cell
maybeZero = (x) =>
x === undefined ? constant(0) : typeof x === "number" ? constant(x) : x
Insert cell
constant = (x) => () => x
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