Public
Edited
Nov 10, 2023
1 star
Insert cell
Insert cell
chart = Plot.plot({
title: "Drought and bug infestations killed trees across the Pacific Northwest in 2022",
subtitle: "Each dot represents an area where scientists observed tree deaths",
caption: "Graphic: AP News: Caleb Diehl, Camille Fassett, Data: U.S. Forest Service",
width: Math.max(width, 500),
height: 500,
facet: {data: allDieOffs, x: 'event', label: null, marginTop: 20},
color: {scheme: 'Oranges', legend: true, label: 'Darker means more areas with damaged trees' },
projection: {type: 'mercator', domain: circle },
marks: [
Plot.geo(dougfir, { fill: 'lightgrey', facet: 'include' }),
Plot.geo(firs, { fill: 'lightgrey', facet: 'exclude' }),
Plot.density(allDieOffs, {
x: "longitude",
y: "latitude",
fx: 'event',
bandwidth: 12,
fill: "density",
weight: d => Math.log(d['ACRES'])
}),
Plot.dot(allDieOffs, {
x: "longitude",
y: "latitude",
r: 1,
fill: "#333",
}),
Plot.geo(states, { fill: 'none', strokeOpacity: .2}),
Plot.geo(nation, { strokeOpacity: 1 }),
Plot.text(states, Plot.centroid({text: (d) => d.properties.name, fill: "currentColor", stroke: "white"})),
Plot.text(["Range of\nDouglas fir"], {facet: 'include', fill: "black", textAnchor:'left', stroke: "#FFF", fontSize: '.875rem', x: -122, y: 46}),
Plot.text(["Range of white,\nsubalpine\nand grand firs"], {facet: 'exclude', fill: "black", textAnchor:'left', stroke: "#FFF", fontSize: '.875rem', x: -122, y: 46.2}),

// facet labels
Plot.text(["Douglas fir"], {facet: 'include', fill: "black", textAnchor:'middle', stroke: "#FFF", fontSize: '1rem', strokeWidth: 5, fontWeight: 'bold', x: -120.5, y: 47.3}),

Plot.text(["True firs"], {facet: 'exclude', fill: "black", textAnchor:'middle', strokeWidth: 5, fontWeight: 'bold', stroke: "#FFF", fontSize: '1rem', x: -120.5, y: 47.3})

]
})
Insert cell
firmageddon = FileAttachment("firmageddon_centroids_proj.csv").csv()
Insert cell
circle = d3.geoCircle().center([-120, 44.5]).radius(3)()
Insert cell
nation = topojson.feature(us, us.objects.nation)
Insert cell
states = topojson.feature(us, us.objects.states).features.filter(d => ["Washington", "Oregon", "California", "Montana", "Idaho"].includes(d.properties.name) )
Insert cell
statemesh = topojson.mesh(us, us.objects.states, (a, b) => a !== b)
Insert cell
counties = topojson.feature(us, us.objects.counties)
Insert cell
us = FileAttachment("us-counties-10m.json").json()
Insert cell
Insert cell
flatHeadDrought = mortality.filter(d => [15041, 50003].includes(d.DCA_CODE))
Insert cell
dougfir_extent = FileAttachment("dougfir_extent.json").json()
Insert cell
dougfir = topojson.feature(dougfir_extent, dougfir_extent.objects.dougfir_extent_compressed)
Insert cell
allDieOffs = [...flatHeadDrought.map(d => ({...d, event: ''})), ...firmageddon.map(d => ({...d, event: ' '}))]



Insert cell
true_firs = FileAttachment("true_firs@2.json").json()
Insert cell
Object.values(true_firs.objects)
Insert cell
firs = {
return {type: "FeatureCollection", features: [ topojson.merge(true_firs, Object.values(true_firs.objects) )
]}
}
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