Published
Edited
Dec 14, 2020
1 fork
Importers
9 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
NotebookLastUpdated = new Date("2020-04-27 16:35")
Insert cell
Insert cell
Insert cell
IllinoisCovidMapES = {
const outerContainer = html`<div style="max-width: 700px;">${style()}</div>`;
const container = html`<div style="width: 100%; height:400px;"></div>`;

const lang = "es";

outerContainer.appendChild(header(lang));
outerContainer.appendChild(mapLegend(lang));
outerContainer.appendChild(container);
outerContainer.appendChild(footer(lang));

yield outerContainer;

// yield outerContainer; // Give the container dimensions.
const map = new mapboxgl.Map({
container,
style: "mapbox://styles/chicagoreporter/ck7z7c9fj1l5j1ipqgdoop32s",
scrollZoom: true
});

map.addControl(new mapboxgl.NavigationControl());

// This stuff should really be loaded into a helper/callback
map.on("load", () => {
map.fitBounds(IllinoisBoundingBox);

// This is so bad! But there's not a great way to wait for fitBounds to end that I've found.
setTimeout(d => {
const bounds = map.getBounds();
map.setMaxBounds(bounds);
}, 500);

map.addSource("counties", {
type: "geojson",
data: IllinoisCountyCovidGeoDataPolygons
});

map.addLayer({
id: "countiesFillLayer",
type: "fill",
source: "counties",
layout: {},
paint: {
"fill-color": "rgba(255, 255, 255, 0.01)"
}
});

// We use D3 to construct an equivalent scale in mapbox
const choroplethStops = [...breaks.slice(1), maxMeasure]
.map(d => [countColor(d - 1), d + 1])
.flat();

map.addLayer(
{
id: "dataLayer",
type: "fill",
source: "counties",
layout: {},
paint: {
'fill-color': [
'step',
['get', selectedMeasure],
"rgba(255, 255, 255, 1)",
1,
...choroplethStops.slice(0, choroplethStops.length - 1)
]
}
},
layerBefore
);

map.addLayer(
{
id: "countiesLayer",
type: "line",
source: "counties",
layout: {},
paint: {
"line-width": .9,
"line-color": "rgba(220, 220, 220, 0.7)"
}
},
layerBefore
);

// Create a popup, but don't add it to the map yet.
let popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});

map.on('mousemove', 'dataLayer', function(e) {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';

const feature = e.features[0];

const popupContent = `
<h1>${feature.properties.County} ${
feature.properties.County === "Chicago" ? "" : "county"
}</h1>
<table>
<tr>
<th>${lang === "es" ? "Confirmado" : "Confirmed"}</th>
<td>${feature.properties.confirmed_cases}</td>
</tr>
<tr>
<th>${lang === "es" ? "Muerto" : "Deaths"}</th>
<td>${feature.properties.deaths}</td>
</tr>
<table>
`;
popup
.setLngLat(e.lngLat)
.setHTML(popupContent)
.addTo(map);
});

map.on('mouseleave', 'dataLayer', function() {
map.getCanvas().style.cursor = '';
popup.remove();
});
});
await triggerEmbedAnalytics("IL county map");

invalidation.then(() => map.remove());

// return outerContainer;
}
Insert cell
Insert cell
Insert cell
Insert cell
maxMeasure = d3.max(
IllinoisCountyCovidGeoDataPolygons.features,
d => d.properties[selectedMeasure]
)
Insert cell
scheme = d3.schemeOranges[9].slice(1, 7)
Insert cell
Insert cell
Insert cell
Insert cell
style = () => html`<style>
.mapboxgl-popup-content h1 {
font-size: 12px;
}
.mapboxgl-popup-content table {
font-size: 10px;
}
.mapboxgl-popup-content table td,
.mapboxgl-popup-content table th,
.mapboxgl-popup-content table tr
{
padding: 1px;
}
</style>`
Insert cell
height = width > 700 ? width * .45 : 300
Insert cell
IllinoisBoundingBox = [
[-94.30530163755736, 36.74643211733368],
[-83.39230352848888, 42.63997206897545]
]
Insert cell
Insert cell
caseTableEN = caseTable()
Insert cell
caseTableES = caseTable("es")
Insert cell
Insert cell
rateFormatter = d3.format("0.1f")
Insert cell
populationFormatter = d3.format(",.3r")
Insert cell
tableColumns = lang => {
const baseColumns = [
{
name: lang === "es" ? "Condado" : "County",
formatter: d =>
html`<span class="${slugCounty(d.properties.County)}">${
d.properties.County === "Cook" ? "Suburban Cook" : d.properties.County
}</span>`
},
{
name: lang === "es" ? "Casos" : "Cases",
formatter: d =>
html`<span class="${slugCounty(
d.properties.County
)}">${d.properties.confirmed_cases.toLocaleString()}</span>`,
justify: "flex-end"
},
{
name: lang === "es" ? "Muerto" : "Deaths",
formatter: d =>
html`<span class="${slugCounty(
d.properties.County
)}">${d.properties.deaths.toLocaleString()}</span>`,
justify: "flex-end"
}
];

const smallColumns = [
{
name: lang === "es" ? "Casos por 1,000" : "Cases per 1,000",
formatter: d =>
html`<span class="${slugCounty(d.properties.County)}">${rateFormatter(
(1000 * d.properties.confirmed_cases) / d.properties.DP05_0001E
)}</span>`,
justify: "flex-end"
}
];

const largeColumns = [
{
name: lang === "es" ? "Tasa de mortalidad" : "Death rate",
formatter: d =>
html`<span class="${slugCounty(d.properties.County)}">${rateFormatter(
(d.properties.deaths / d.properties.confirmed_cases) * 100
)}%</span>`,
justify: "flex-end"
},
{
name: lang === "es" ? "Población total" : "Total population",
formatter: d =>
html`<span class="${slugCounty(
d.properties.County
)}">${populationFormatter(d.properties.DP05_0001E)}</span>`,
justify: "flex-end"
}
];

if (width < 480) {
return baseColumns;
} else if (width < 700) {
return [...baseColumns, ...smallColumns];
} else {
return [...baseColumns, ...smallColumns, ...largeColumns];
}
}
Insert cell
slugCounty = str => str.toLowerCase().replace(" ", "")
Insert cell
Insert cell
Insert cell
translationsEN = ({
confirmed_cases: "Confirmed cases",
deaths: "Deaths"
})
Insert cell
md`# Stats

Uses code from https://observablehq.com/@jdev42092/jenks-breaks-using-simple-statistics.
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function triggerEmbedAnalyticsEvent(category, action, label) {
if (location.hostname.includes("observableusercontent.com")) {
console.log(
{ category, action, label },
"Skipping embed analytic event, would send:"
);
return;
}
try {
await ga;
ga('covidembed.send', 'event', category, action, label);
} catch {
console.log('Chicago Reporter embed analytics failed');
}
}
Insert cell
Insert cell
Insert cell
IllinoisHistoricalData = d3.csvParse(
await FileAttachment(
"COVID-19 Illinois by day - through March 17 - statewide.csv"
).text(),
d => {
d.date = new Date(d.date);
return d;
}
)

// Previously pulled from: https://docs.google.com/spreadsheets/d/e/2PACX-1vQYpPcDFRChDlYT0xnGge5Jwbpl6xIp77nCWD-x5SvK54Nr06u3h3DmsN8GUAfKTLZbcVQWRb83lpUX/pub?gid=0&single=true&output=csv
// Now attached to this notebook
Insert cell
cdnRootUrl = "https://d38afsumxukqre.cloudfront.net/sites/default/files/COVID19/"
Insert cell
cdnRoot = "https://d38afsumxukqre.cloudfront.net/"
Insert cell
Insert cell
import { legend } from "@d3/color-legend"
Insert cell
import { HyperGrid } from "@chicagoreporter/hypergrid"
Insert cell
Insert cell
import { select } from "@jashkenas/inputs"
Insert cell
mapboxgl = {
const gl = await require("mapbox-gl@1.8.1");
if (!gl.accessToken) {
gl.accessToken =
"pk.eyJ1IjoiY2hpY2Fnb3JlcG9ydGVyIiwiYSI6ImNrN3kwZ2ZjNTAwNWczZW55N3dseGk3dTkifQ.8xPIVZq_YU73F3EWkkoQsA";
const href = await require.resolve("mapbox-gl@1.8.1/dist/mapbox-gl.css");
document.head.appendChild(html`<link href=${href} rel=stylesheet>`);
}
return gl;
}
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