Published
Edited
Dec 29, 2020
Importers
6 stars
Insert cell
Insert cell
viewof metric = radio({title: "color", options: [{value: "change", "label": "rate of change"}, "percapita"], value:"percapita"})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
state_field = {
if (transform == "change") {
return `change_${state_metric}`
}
if (transform == "number") {
return `rolling_${state_metric}`
}
if (transform == "Per capita") {
return `${state_metric}_per_capita`
}
}
Insert cell
Insert cell
times = aq
.fromCSV(await d3.text('https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv'))
.derive({fips: d => d.fips ? d.fips : d.county=="New York City" ? "36061" : d.county=="Kansas City" ? "29380" : d.fips})
Insert cell
times2 = times
.groupby(["state", "fips"])
.orderby("date")
.derive({"new": d => d.cases - op.lag(d.cases, 1, 0)})
Insert cell
function fill_zeros(frame, cola, colb) {
// must have a column called 'count'.
const values = frame.select([cola]).dedupe().join_full(frame.select([colb]).dedupe(), [[], []])
const names = frame.columnNames().filter(d => d != cola && d!==colb)
return frame
.join_full(values, [[cola, colb], [cola, colb]], [names, [cola, colb]])
.derive({count: d => d.count ? d.count : 0})
}
Insert cell
times2.columnNames()
Insert cell
covid_tracking = d3.csv("https://api.covidtracking.com/v1/states/daily.csv").then(d => d.map(e => {
e.date = d3.timeParse("%Y%m%d")(e.date);
for (let field of ["positiveIncrease", "deathIncrease", "hospitalizedCurrently"]) {
e[field] = +e[field]
}
return e}))
Insert cell
viewof covid_tracking_states =
{
const rawest = aq.from(covid_tracking)
.select(["date", "state", "positiveIncrease", "deathIncrease", "hospitalizedCurrently"])
const dates = rawest.select("date").dedupe().reify()
const unique_states = rawest.select("state").dedupe().reify()
const all_combos = dates.join_full(unique_states, [[], []])
let filled_a_bit = rawest
.join_full(all_combos, [['date', 'state'], ['date', 'state']], [["positiveIncrease", "deathIncrease", "hospitalizedCurrently"], ['date', 'state']])
// fill NA.
.derive({
"positive": d => d.positiveIncrease ? d.positiveIncrease : 0,
"rolling_hospitalized": d => d.hospitalizedCurrently ? d.hospitalizedCurrently : 0,
"deaths": d => d.deathIncrease ? d.deathIncrease : 0}
)
.join(states, [["state"], ["state_abbr"]], [["positive", "date", "state", "rolling_hospitalized", "deaths"], ["pop"]])
.groupby("state")
.orderby("date")
.params({lag: TIME_HORIZON})
.derive({"rolling_positive": aq.rolling((d, $) => op.sum(d.positive), [-TIME_HORIZON, 0]),
"rolling_deaths": aq.rolling((d, $) => op.sum(d.deaths), [-TIME_HORIZON, 0])
})
.derive(
{"change_positive": (d, $) => d.rolling_positive / op.lag(d.rolling_positive, $.lag),
"change_deaths": (d, $) => d.rolling_deaths / op.lag(d.rolling_deaths, $.lag),
"change_hospitalized": (d, $) => d.rolling_hospitalized / op.lag(d.rolling_hospitalized, $.lag)
})
.derive(
{"positive_per_capita": (d, $) => d.rolling_positive / d.pop,
"deaths_per_capita": (d, $) => d.rolling_deaths / d.pop,
"hospitalized_per_capita": (d, $) => d.rolling_hospitalized / d.pop
}).select(["state", "date",
"positive_per_capita", "deaths_per_capita", "hospitalized_per_capita",
"change_positive", "change_deaths", "change_hospitalized",
"rolling_positive", "rolling_deaths", "rolling_hospitalized"])


return filled_a_bit.view()
}
Insert cell
re_rolled = {
// return all_combos
const dates = times2.select("date").dedupe().reify()
const states = times2.select("state").dedupe().reify()
const all_combos = dates.join_full(states, [[], []])
return times2.groupby(["date", "state"])
.rollup({"new": d => op.sum(d.new)})
.join_full(all_combos, [['date', 'state'], ['date', 'state']], [['new'], ['date', 'state']])
// fill NA.
.derive({"new": d => d.new ? d.new : 0})
}
Insert cell
Insert cell
with_pops = re_rolled
.groupby("state")
.orderby("date")
.derive({"new": aq.rolling(d => op.sum(d.new), [-7, 0])})
.derive({"change": d => d.new / op.lag(d.new, 7)})
.join(states, [["state"], ["state_name"]], [["new", "date", "state", "change"], ["pop"]])
.derive({percapita: d => d.new / d.pop})

Insert cell
Insert cell
Insert cell
msas = aq.table({"fips": Object.keys(metros), "msa": Object.values(metros)})
Insert cell
best_sorting_order = [
["Pacific Ocean", "Guam AKA GU", "Hawaii AKA HI", "Alaska AKA AK"],
["Lower 48",
["West",
["West Coast",
["Pacific Northwest", "WA", "OR"],
"CA"
],
["Southwest", "AZ", "NM", "NV"],
"CO",
"WY",
"UT",
"ID",
"MT"
],
["Midwest",
["Dakotas", "ND","SD"],
"NE","KS","IA",
"MN","WI", "MI", "OH","IN","IL"
],
["South", "MO",
"OK","TX","LA","AR",
"KY","TN",
"MS","AL","GA","FL",
"SC","NC","WV","VA"],
["Northeast",
["Mid-Atlantic",
"DC","MD","DE","PA","NJ","NY"
],
["New England",
["Southern New England",
"CT","RI","MA"],
["Northern New England", "NH","VT","ME"]
]
],
["Carribean", "Puerto Rico AKA PR", "US Virgin Islands"]
]
].flat(10).map(k => [k, state_info.get(k) ? state_info.get(k).state_name : undefined]).flat().filter(d => d!=undefined)
Insert cell
function cleanup(frame, populations, groups = ["state"], date = "date") {
return frame
// .derive({"date": d => op.week(d[date])})
// .derive({"date": d => new Date(2020, 0, 7 * d.date)})
.groupby([...groups, date])
.rollup({count: d => op.sum(d.new)})
.join_left(populations, [groups, groups], [[...groups, "date", "count"], ["pop"]])
.groupby(groups)
.derive({change: d => d.count/op.lag(d.count, 1, 1), "percapita": d => d.count/d.pop})
}
Insert cell
state_pops = {
const pops = await d3.json("https://raw.githubusercontent.com/CivilServiceUSA/us-states/master/data/states.json").then(d => d3.rollup(d, data => data[0].population, k => k.code))
pops.set("PR", 2860853)
pops.set("DC", 684498)
return pops
}
Insert cell
Insert cell
viewof states = aq.from(state_info.values()).dedupe().view()
Insert cell
Insert cell
Insert cell
root_ordering = countries.array
Insert cell
aliases = countries.alias_map()
Insert cell
import { countries } from '12cd50fc650b98a9';
Insert cell
viewof country_cases = {
const unfull = aq
.from(hopkins)
.groupby(["Country/Region", "Province/State"]).orderby("date")
.derive({new: d => d.positive - op.lag(d.positive, 1, 0)})
.groupby(["Country/Region", "date"])
.rollup({count: d => op.sum(d.new)})
.filter(d => d.count > 0)
const filled = fill_zeros(unfull, "Country/Region", "date")
populations.forEach(d => d.population_total = +d.population_total)

return filled.join_left(aq.from(populations), [["Country/Region"], ["name"]],
[filled.columnNames(), ['population_total']])
.derive({pop: d => d.population_total})
.groupby("Country/Region")
.derive({share: d => d.count/op.sum(d.count)})
.orderby("date")
.derive({"new": aq.rolling((d, $) => op.sum(d.count), [-TIME_HORIZON, 0])})
.params({TIME_HORIZON: TIME_HORIZON})
.derive({"change": (d, $) => d.new / op.lag(d.new, $.TIME_HORIZON)})
.derive({percapita: d => d.new / d.pop})
.filter(d => d["Country/Region"] !== undefined)
.view(10)
}
Insert cell
populations = populations_raw.map(d => {
// Add some additional possible populations.
const output = []
for (let alias of aliases.get(d.name)) {
output.push({"name": alias, "population_total": d.population_total})
}
return output
}).flat(1)
Insert cell
Insert cell
embed = require("vega-embed@6")
Insert cell
metros = d3.json("https://gist.githubusercontent.com/bmschmidt/62ed8da02750cbf0b75278cfe06f7bb7/raw/37cc7dfe54b71c041fbc2d3d9cd214443d206c3c/msa-csa.json")
Insert cell
d3 = require("d3@v6")
Insert cell
import { aq, op } from '@uwdata/arquero'
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