Public
Edited
Jun 7, 2023
Insert cell
Insert cell
map(width)
Insert cell
Insert cell
air = d3
.text(
"https://www.airnowapi.org/aq/data/?startDate=2023-06-07T12&endDate=2023-06-07T13&parameters=PM25&BBOX=-130,25,-65,55&dataType=A&format=text/csv&verbose=0&monitorType=0&includerawconcentrations=0&API_KEY=62F6D106-6781-4DC5-8A63-005044B666E2"
)
.then((d) =>
d3.csvParse("lat,lon,date,indicator,PM2.5,??\n" + d, d3.autoType)
)
Insert cell
// Here’s a copy, in case the API stops working
// air = FileAttachment("air.csv").csv({typed: true})
Insert cell
Insert cell
color = ({
label: "PM2.5",
type: "threshold",
domain: [50, 100, 150, 200, 300],
range: [
"rgb(156, 216, 78)", // Good
"rgb(250, 207, 57)", // Moderate
"rgb(249, 144, 73)", // Unhealthy for Sensitive Groups
"rgb(246, 94, 95)", // Unhealthy
"rgb(160, 112, 182)", // Very Unhealthy
"rgb(160, 106, 123)" // Hazardous
]
})
Insert cell
Insert cell
Insert cell
Plot.plot({
color,
marks: [
Plot.dot(air, {
x: "lon",
y: "lat",
fill: "PM2.5",
r: 4,
stroke: "white"
})
]
})
Insert cell
Insert cell
Plot.plot({
projection: "albers",
color,
marks: [
Plot.dot(air, {
x: "lon",
y: "lat",
fill: "PM2.5",
stroke: "white",
fx: "date"
})
]
})
Insert cell
// Group by date, and return the group with the largest key.
recent = d3
.greatest(
d3.group(air, (d) => d.date),
(d) => d[0]
)[1]
.filter((d) => d["PM2.5"] > 0) // remove the points with value -999
Insert cell
Insert cell
visibility().then(() => map(width))
Insert cell
// this is a function because we want to show the map at the top of the page.
map = (width) =>
Plot.plot({
width,
projection: "albers",
color: { ...color, legend: true },
marks: [
// this creates a path to clip the contour mark.
Plot.geo(nation, {
render: (i, s, v, d, c, next) => {
const g = next(i, s, v, d, c).children[0];
return svg`<clipPath id=nation>${g}`;
}
}),

Plot.contour(recent, {
x: "lon",
y: "lat",
fill: "PM2.5",
interpolate: "random-walk",
blur: 3,
thresholds: [0, ...color.domain],
stroke: "currentColor",
render: (i, s, v, d, c, next) => {
const g = next(i, s, v, d, c);
g.setAttribute("clip-path", "url(#nation)"); // add clip
return g;
}
}),

Plot.geo(nation, { stroke: "currentColor" }),

Plot.dot(recent, {
x: "lon",
y: "lat",
fill: "PM2.5",
stroke: "currentColor",
strokeOpacity: 0.8,
strokeWidth: 0.75,
tip: true
})
]
})
Insert cell
us = FileAttachment("us-counties-10m.json").json()
Insert cell
nation = topojson.feature(us, us.objects.nation)
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