Published
Edited
Aug 11, 2021
Insert cell
md`# Connecticut cases and deaths`
Insert cell
viewof covid = {
const cases = vl.markArea()
.data(pdata)
.encode(
vl.x().fieldT("date").axis({title:'Date (starting March 1, 2020)'}),
vl.y().fieldQ("smooth").axis({title: `New Cases (${sp} day average)`,orient:'right', 'minExtent':0}),
vl.color().fieldN('county'),) ;
const deaths = vl.markLine().data(totalsmoothdeaths)
.encode(
vl.x().fieldT("date").axis({title:'Date (starting March 1, 2020)'}),
vl.y().fieldQ("smooth").axis({title: `Deaths (${sp} day average)`,orient:'right'}))
return vl.vconcat(cases,deaths)
.render() ;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data
Insert cell
// get the new case numbers and the smoothed ones

function filter(data,state,county,window) {
let filtered = data.filter(x=>(x.state==state && x.county==county && x.date>='2020-03-01')) ;
filtered = filtered.sort((a, b) => d3.ascending(a.date,b.date));
filtered[0].new_cases = +filtered[0].cases ;
for (let i=1;i<filtered.length; i++) {
filtered[i].new_cases = filtered[i].cases - filtered[i-1].cases ;
}
let smoothed = movingAverage(filtered.map(x=>x.new_cases),window)
for (let i=0;i<filtered.length;i++) {
filtered[i].smooth = smoothed[i]>0?smoothed[i]:0 ;
}
return filtered.filter(x=>x.smooth) ;
}
Insert cell
function filter2(data,state,county,window) {
let filtered = data.filter(x=>(x.state==state && x.county==county && x.date>='2020-03-01')) ;
filtered = filtered.sort((a, b) => d3.ascending(a.date,b.date));
filtered[0].new_deaths = +filtered[0].deaths ;
for (let i=1;i<filtered.length; i++) {
filtered[i].new_deaths = filtered[i].deaths - filtered[i-1].deaths ;
}
let smoothed = movingAverage(filtered.map(x=>x.new_deaths),window)
for (let i=0;i<filtered.length;i++) {
filtered[i].smooth = smoothed[i]>0?smoothed[i]:0 ;
}
return filtered.filter(x=>x.smooth) ;
}
Insert cell
ctcounties = ["Fairfield","Middlesex","Litchfield","New London","New Haven","Tolland","Windham", "Hartford"]
Insert cell
pdata = ctcounties.map(x=>filter(data,'Connecticut',x,sp)).flat()
Insert cell
function movingAverage(values, N) {
let i = 0;
let sum = 0;
const means = new Float64Array(values.length).fill(NaN);
for (let n = Math.min(N - 1, values.length); i < n; ++i) {
sum += values[i];
}
for (let n = values.length; i < n; ++i) {
sum += values[i];
means[i] = sum / N;
sum -= values[i - N + 1];
}
return means;
}
Insert cell
pdata.sort((a,b)=>d3.descending(Date.parse(a.date),Date.parse(b.date)))
Insert cell
pdata.map(x=>(Date.parse(x.date)))
Insert cell
pdata
Insert cell
Date.parse("2020-05-09")
Insert cell
f = ctcounties.map(x=>filter2(data,'Connecticut',x,sp)).flat()
Insert cell
f.sort((a, b) => d3.ascending(a.date,b.date));
Insert cell
f.new_deaths
Insert cell
h=d3.group(f,d=>d.date)
Insert cell
totalsmoothdeaths = {
let new_deaths = d3.rollup(f,v=>d3.sum(v,d=>d.new_deaths),d=>d.date);
let smoothed_deaths=movingAverage(Array.from(new_deaths.values()),sp) ;
let dates = Array.from(new_deaths.keys()) ;
let m=d3.zip(dates,smoothed_deaths)
const totalsmoothdeaths=m.map(x=>({date:x[0],smooth:x[1],county: "Deaths"}))
return totalsmoothdeaths;
}
Insert cell
viewof dline = vl.markLine()
.data(totalsmoothdeaths)
.encode(
vl.x().fieldT("date").axis({title:'Date (starting March 1, 2020)'}),
vl.y().fieldQ("smooth").axis({title: `New Cases (${sp} day average)`,orient:'right'}))
.render()
Insert cell
pdata
Insert cell
combined=d3.merge([pdata,totalsmoothdeaths])
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