Published
Edited
Apr 22, 2022
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
chart = Plot.plot({
inset: 0,
margin: 50,
padding: 0.0625,
axis: false,
width,
height: width > minWidth ? (width * 9) / 8 : width * 6,
color: {
scheme: "RdYlBu",
type: "diverging"
},
x: { inset: 1, domain: [0, 1] },
y: { inset: 1, domain: [0, 1] },
facet: {
data,
y: (d) =>
width > minWidth
? (findState(isoToVehicleCode(d.state)) || {}).y
: states.findIndex((s) => s.id === isoToVehicleCode(d.state)),
x: (d) =>
width > minWidth ? (findState(isoToVehicleCode(d.state)) || {}).x : 0
},
marks: [
// Plot.frame({ stroke: "none", fill: `hsla(0,0%,0%,0.0125)` }),
Plot.text(
data,
Plot.selectFirst({
text: (d) => findState(isoToVehicleCode(d.state)).name,
dx: -10,
dy: 2.5,
fill: colors.gray[600],
fontSize: 12,
frameAnchor: "bottom-right",
lineWidth: 7.5,
lineHeight: 1.25,
stroke: "white",
strokeWidth: 0.5
})
),
Plot.vector(
data,
Plot.selectLast({
x: 1,
y: 0, //(d) => d.delta.confirmed || 0,
rotate: (d) => (d.delta.confirmedAngle * -180) / Math.PI + 90,
anchor: "start",
stroke: (d) => -1 * d.delta.confirmedAngle,
length: 40,
strokeWidth: 4
})
),
Plot.dot(
data,
Plot.selectLast({
x: 1,
y: 0, // (d) => d.delta.confirmed || 0,
fill: (d) => -1 * d.delta.confirmedAngle,
r: 6
})
)
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
getStatePopulation = (id) => meta.population[id].population
Insert cell
normalizeByStatePopulationPer = (value, stateId, per = 100) =>
(value * per) / getStatePopulation(stateId)
Insert cell
data = {
const lastDays = 90;
let arr = [];
for (const [stateId, stateObj] of Object.entries(json)) {
// Ignore blacklisted state ids
if (stateBlacklist.includes(stateId)) continue;

// Flatten state data into array
const stateData = [];
for (const [dateString, d] of Object.entries(stateObj.dates)) {
// Ignore negative confirmed cases
if (d.delta.confirmed < 0) continue;

const date = new Date(dateString);
// Ignore data which are excluded
if (
lastDays !== null &&
d3.timeDay.count(date, meta.lastUpdated) > lastDays
)
continue;

stateData.push({
...d,
date
});
}

// Compute moving avg for delta.confirmed
let values = stateData
.map((s) => s.delta.confirmed)
.filter((v) => v !== null)
.map((v) => normalizeByStatePopulationPer(v, stateId, valuePer));
let averages = Array.from(movingAverage(values, movingAverageDays))
.slice(-1 * movingAverageDays)
.map((d, i) => [i, d]);
const slope = model(averages).m;
const angle = Math.atan(slope);

stateData[stateData.length - 1].delta.confirmedSlope = slope;
stateData[stateData.length - 1].delta.confirmedAngle = angle;

stateData.forEach((s) => {
arr.push({
...s,
state: stateId
});
});
}

arr = arr.filter((d) => d.delta.confirmedSlope !== undefined);

return arr;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
valuePer = 1e7 // per Crore
Insert cell
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