Unlisted
Edited
Mar 31
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
bls = FileAttachment("bls-metro-unemployment.csv").csv({ typed: true })
Insert cell
bls
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
industries = FileAttachment("industries.csv").csv({ typed: true })
Insert cell
industries
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
filteredIndustries = industries.filter(
(d) =>
d.industry === "Manufacturing" ||
d.industry === "Wholesale and Retail Trade"
)
Insert cell
Insert cell
filteredPenguins = penguins
//.slice(0, 5)
.filter((obj) =>
Object.values(obj).every(
(value) => !(typeof value === "number" && isNaN(value))
)
)
Insert cell
filteredPenguins
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
width,
height: 800,
y: {
grid: true,
label: "↑ Unemployment (%)"
},
marks: [
Plot.ruleY([0]),
Plot.lineY(bls, {
x: "date",
y: "unemployment",
z: "division",
stroke: "lightgrey"
}),
Plot.lineY(
bls,
Plot.pointer({
x: "date",
y: "unemployment",
z: "division",
//stroke: "division", // lines don't need an explicit z
render: (index, scales, values, dimensions, context, next) => {
// Filter and highlight the paths with the same *z* as the hovered point.
const path = d3
.select(context.ownerSVGElement)
.selectAll("[aria-label=line] path");
if (index.length) {
const z = values.z[index[0]];
path
.style("stroke", "black")
.filter(([i]) => values.z[i] != z)
.style("stroke", null)
.raise();
} else path.style("stroke", null);
return next(index, scales, values, dimensions, context);
}
})
),
Plot.tip(
bls,
Plot.pointer({
x: "date",
y: "unemployment",
z: "division"
})
)
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
focus = Generators.input(chart)
Insert cell
Insert cell
Insert cell
Plot.plot({
width,
height: 800,
marks: [
Plot.dot(filteredPenguins, {
x: "culmen_length_mm",
y: "culmen_depth_mm"
}),
Plot.dot(
filteredPenguins,
Plot.pointer({
x: "culmen_length_mm",
y: "culmen_depth_mm",
render: (index, scales, values, dimensions, context, next) => {
// Filter and highlight the paths with the same *z* as the hovered point.
const svg = d3.select(context.ownerSVGElement);
const circles = svg.selectAll("[aria-label=dot] circle");

if (index.length) {
const x = values.x[index[0]];
const y = values.y[index[0]];

circles
.style("stroke", "blue")
.style("fill", "red")
.attr("r", 8)
.filter((i) => values.x[i] != x || values.y[i] != y)
.style("stroke", null)
.style("fill", null)
.attr("r", 3)
.raise();
} else circles.style("stroke", null).style("fill", null).attr("r", 3);
return next(index, scales, values, dimensions, context);
}
})
),
Plot.tip(
filteredPenguins,
Plot.pointer({
x: "culmen_length_mm",
y: "culmen_depth_mm"
})
)
]
})
Insert cell
Insert cell
mutable startEnd = null
Insert cell
setStartEnd = (se) => (mutable startEnd.value = se)
Insert cell
Plot.plot({
marks: [
Plot.ruleY([0]),
Plot.lineY(aapl, { x: "Date", y: "Close" }),
(index, scales, channels, dimensions, context) => {
const x1 = dimensions.marginLeft;
const x2 = dimensions.width - dimensions.marginRight;
const y1 = 0;
const y2 = dimensions.height;
const brushed = (event) =>
setStartEnd(event.selection?.map(scales.x.invert));
const brush = d3
.brushX()
.extent([
[x1, y1],
[x2, y2]
])
.on("brush end", brushed);
return d3.create("svg:g").call(brush).node();
}
]
})
Insert cell
Insert cell
Insert cell
import { toc } from "41c75be397ee13a5"
Insert cell
Insert cell
Insert cell
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