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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more