Public
Edited
Aug 10, 2020
Insert cell
Insert cell
Insert cell
Insert cell
lastUpdated = md`**Stats last updated ${stats
.get('date')
.toLocaleDateString()}**`
Insert cell
Insert cell
casesGraph = {
const svg = d3
.create('svg')
.attr('viewBox', [0, 0, 460, 630])
.style('width', '400px');

svg
.append('g')
.attr('transform', 'translate(50,20)')
.append(() => legend({ color: casesColor, title: 'Cases', width: 260 }));

const color = d => casesColor(numCases.get(d.properties.name));
svg
.append('g')
.selectAll('g')
.data(topojson.feature(ri, ri.objects.counties).features)
.join('g')
.call(g =>
g
.append('path')
.attr('fill', color)
.attr('d', path)
)
.call(
labelCounties(color, d =>
d3.format(',.0f')(numCases.get(d.properties.name))
)
);

return svg.node();
}
Insert cell
casesColor = d3
.scaleSequential(t => d3.interpolateOrRd(Math.pow(t, 1 / 1.5)))
.domain([0, d3.max(Array.from(numCases.values()))])
.nice()
Insert cell
Insert cell
percentInfectedGraph = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, 460, 630])
.style("width", "400px");

svg
.append("g")
.attr("transform", "translate(50,20)")
.append(() =>
legend({
color: percentInfectedColor,
title: "Percent Infected",
width: 260,
tickFormat: '%'
})
);

const percent = d =>
numCases.get(d.properties.name) / populations[d.properties.name];
const color = d => percentInfectedColor(percent(d));
svg
.append('g')
.selectAll('g')
.data(topojson.feature(ri, ri.objects.counties).features)
.join('g')
.call(g =>
g
.append('path')
.attr("fill", color)
.attr("d", d3.geoPath(projection))
)
.call(labelCounties(color, d => d3.format('.4%')(percent(d))));

return svg.node();
}
Insert cell
percentInfectedColor = d3
.scaleSequential(d3.interpolateBlues)
.domain([
0,
d3.max(Array.from(numCases.entries()), d => d[1] / populations[d[0]])
])
Insert cell
Insert cell
stats = {
const text = await d3.text(
'https://cors-anywhere.herokuapp.com/docs.google.com/spreadsheets/d/1c2QrNMz8pIbYEKzMJL7Uh2dtThOJa2j1sSMwiDo5Gz4/export?format=csv'
);
const [firstLine, ...rest] = text.split('\r\n');
const date = d3.timeParse('%-m/%-d/%Y')(firstLine.split(',')[1]);
const map = new Map(
d3.csvParseRows(rest.join('\n'), ([name, value]) => [
name
.replace(/\s*\([^)]+\)/g, '')
.replace(/\s{2,}/g, ' ')
.trim(),
parseInt(value.replace(/,/g, ''))
])
);
map.set('date', date);
return map;
}
// stats = d3
// .text('https://j-f1.github.io/ridoh-covid19-key-stats/latest.csv?v=1')
// .then(text => d3.csvParseRows(text, d3.autoType))
// .then(rows => new Map(rows))
// stats = d3.json(
// 'https://raw.githubusercontent.com/j-f1/covid19-map/master/key_stats.json'
// )
Insert cell
numCases = csvRows(
'https://cors-anywhere.herokuapp.com/docs.google.com/spreadsheets/d/e/2PACX-1vT--dFc7nR7jA_yu24aZYX_uVpa2grOddI7Zx2j4tFZRXasOL0Ldr6l_uAMmoOf77WV5jZsKNNg53eH/pub?output=csv',
([name, count]) => [name.toUpperCase(), parseInt(count)]
).then(rows => new Map(rows))
Insert cell
// Source: https://en.wikipedia.org/wiki/List_of_counties_in_Rhode_Island
populations = ({
BRISTOL: 49875,
KENT: 166158,
NEWPORT: 82888,
PROVIDENCE: 626667,
WASHINGTON: 126979
})
Insert cell
Insert cell
projection = d3
.geoAlbers()
.center([-2, 41.8])
.scale(4e4)
.rotate([69, 0, 0])
Insert cell
path = d3.geoPath(projection)
Insert cell
Insert cell
Insert cell
csvRows = (url, handler = d3.autoType) =>
fetch(url)
.then(res => res.text())
.then(csv => d3.csvParseRows(csv, handler))
Insert cell
labelCounties = (color, value) => g =>
g
.call(g =>
makeLabel(g, d => d.properties.name)
.attr('stroke', color)
.attr('stroke-width', 6)
.attr('stroke-opacity', .75)
.attr('dy', -10)
)
.call(g =>
makeLabel(g, d => d.properties.name)
.attr('fill', d => (isDark(color(d)) ? 'white' : 'black'))
.attr('dy', -10)
)
.call(g =>
makeLabel(g, value)
.attr('stroke', color)
.attr('stroke-width', 6)
.attr('stroke-opacity', .75)
.attr('dy', 10)
)
.call(g =>
makeLabel(g, value)
.attr('fill', d => (isDark(color(d)) ? 'white' : 'black'))
.attr('dy', 10)
)
Insert cell
makeLabel = (g, text) =>
g
.append('text')
.attr('transform', d => `translate(${path.centroid(d)})`)
.attr('text-anchor', 'middle')
.attr('font-weight', '900')
.text(text)
Insert cell
pl = n => (n === 1 ? '' : 's')
Insert cell
Insert cell
Insert cell
// require.resolve("topojson-client@3")
Insert cell
topojson = require("https://cdn.jsdelivr.net/npm/topojson-client@3.1.0/dist/topojson-client.min.js")
Insert cell
// require.resolve('d3@5')
Insert cell
d3 = require('https://cdn.jsdelivr.net/npm/d3@5/dist/d3.min.js')
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