Public
Edited
Feb 11, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
raw_state_data = d3.csv('https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-states.csv')
Insert cell
raw_county_data = d3.csv('https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv')
Insert cell
process_data = data => {
const output = data.map((d, i) => ({
date: d.date,
cases: Math.max(d.cases - (data[i - 1] ? data[i - 1].cases : 0), 0),
deaths: Math.max(d.deaths - (data[i - 1] ? data[i - 1].deaths : 0), 0),
total_cases: +d.cases,
total_deaths: +d.deaths,
}));

// The line/area will be shifted to the right by one band, so prepend
// a placeholder value with 0 to the left to make up for it
const dayBefore = new Date(output[0].date);
dayBefore.setDate(dayBefore.getDate() - 1);

output.unshift({
date: d3.utcFormat('%Y-%m-%d')(dayBefore),
cases: 0,
deaths: 0,
total_cases: 0,
total_deaths: 0,
});

Object.assign(output, data[0], {
past_week: d3.sum(output.slice(-7), d => d[type]),
total: output[output.length - 1][`total_${type}`],
});

['date', 'cases', 'deaths'].forEach(key => delete output[key]);

return output;
};
Insert cell
us_data = process_data(
d3
.groups(raw_state_data, d => d.date)
.map(([date, data]) => ({
date,
cases: d3.sum(data, d => d.cases),
deaths: d3.sum(data, d => d.deaths)
}))
)
Insert cell
state_data = d3
.groups(raw_state_data, d => d.state)
.map(([, rows]) => process_data(rows))
Insert cell
active_state_data = state_data.find(d => d.state === state)
Insert cell
county_data = d3
.groups(raw_county_data, d => d.county + d.state)
.map(([, rows]) => process_data(rows))
Insert cell
active_state_counties_data = county_data
.filter(d => d.state === state)
.filter(d => d.total)
.filter(d => d.county !== 'Unknown')
.filter(d => d.county !== 'District of Columbia')
// .filter(d => d.past_week > 100)
.sort((a, b) => d3.descending(a.past_week, b.past_week))
Insert cell
date_extent = {
const extent = d3.extent(raw_state_data, d => d.date)
.map(d => new Date(d));
extent[0].setDate(extent[0].getDate() - 1);
extent[1].setDate(extent[1].getDate() + 1);

return extent;
}
Insert cell
make_chart = (data, width, domain) => {
const bars = vl.markBar({ opacity: 0.1 }).encode(
vl
.x()
.fieldT('date')
.timeUnit('utcyearmonthdate')
.scale({ domain: date_extent.map(d3.utcFormat('%Y-%m-%d')) })
.axis({ tickCount: 'month', format: '%B', grid: false, tickSize: 6 })
.title(null),

vl
.y()
.fieldQ(type)
.scale({ domain, nice: false })
.axis({
tickCount: 4,
domain: false,
ticks: false,
labelAlign: 'left',
labelBaseline: 'bottom'
})
.title(null),

vl.color({ value: 'red' })
);

// Push the line/area layers to the right edge of the bars (1 bandwidth)
const xOffset = width / d3.timeDay.count(...date_extent);

const line = bars
.markLine({ interpolate: 'monotone', xOffset })
.encode(vl.y().fieldQ('mean'));

const area = line.markArea({ opacity: 0.2, xOffset });

return vl
.layer(bars, area, line)
.data(data)
.transform(
vl.window({ op: 'mean', field: type, as: 'mean' }).frame([-3, 3])
)
.width(width)
.height(width / 5)
.autosize({ type: 'fit-x', contains: 'padding' })
.config({
style: { cell: { stroke: 'transparent' } },
axis: { labelColor: '#929292', gridColor: '#ececec' },
padding: { top: 5, right: 0, bottom: 5, left: 0 }
})
.render();
}
Insert cell
make_figure = async (title, data, width, domain) => html`<figure style="max-width: none;">
<figcaption style="margin-bottom: 10px;">
<h3>${title}</h3>
<small style="color: #333;">${data.past_week.toLocaleString('en')} NEW ${type.toUpperCase()} IN PAST WEEK</small><br />
<small>${data.total.toLocaleString('en')} TOTAL ${type.toUpperCase()}</small>
</figcaption>
${await make_chart(data, width, domain)}
</figure>`;
Insert cell
d3 = require("d3@5", "d3-array@2")
Insert cell
import { vl } from "@vega/vega-lite-api"
Insert cell
import { table } from '@gnestor/table'
Insert cell
import { toPascalCase } from "@gnestor/grants-utilities"
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