Published
Edited
Oct 23, 2020
2 stars
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
data = await FileAttachment("electoral_college@3.csv").csv({ typed: true })
Insert cell
contested = data
.filter(d => d.category === "none")
.sort((a, b) => d3.descending(a.votes, b.votes))
Insert cell
totalD = d3.sum(data.filter(d => d.category === "D").map(d => d.votes))
Insert cell
totalR = d3.sum(data.filter(d => d.category === "R").map(d => d.votes))
Insert cell
decided = new Map(
Object.entries(selectStates).filter(([key, value]) => value !== "none")
)
Insert cell
treeData = {
const root = {
name: "",
votes: 0,
votesD: totalD,
votesR: totalR,
pruned: false
};
function buildTree(node, depth) {
if (depth < contested.length && !winner(node)) {
const state = contested[depth];
node.children = [
{
name: state.name,
shortname: state.shortname,
party: "D",
votes: state.votes,
votesD: node.votesD + state.votes,
votesR: node.votesR,
pruned:
node.pruned ||
(decided.has(state.name) && decided.get(state.name) === "R")
},
{
name: state.name,
shortname: state.shortname,
party: "R",
votes: state.votes,
votesD: node.votesD,
votesR: node.votesR + state.votes,
pruned:
node.pruned ||
(decided.has(state.name) && decided.get(state.name) === "D")
}
];
node.children.forEach(child => buildTree(child, depth + 1));
}
return node;
}
return buildTree(root, 0);
}
Insert cell
function autoBox() {
document.body.appendChild(this);
const { x, y, width, height } = this.getBBox();
document.body.removeChild(this);
return [x - 5, y, width + 10, height];
}
Insert cell
tree = d3
.cluster()
.size([2 * Math.PI, radius])
.separation((a, b) => (a.parent == b.parent ? 1 : 2) / a.depth)
Insert cell
radius = 390
Insert cell
targetWidth = Math.min(width, radius * 2)
Insert cell
circleSize = d3
.scaleSqrt()
.domain(d3.extent(contested.map(d => d.votes)))
.range([2.5, 6.5])
Insert cell
votesScale = d3
.scaleLinear()
.domain([0, 538])
.range([0, targetWidth])
Insert cell
result = d =>
d.votesD > 269
? "D"
: d.votesR > 269
? "R"
: d.votesD === 269 && d.votesR === 269
? "tie"
: null
Insert cell
winner = d => {
const outcome = result(d);
return !outcome || outcome === "tie" ? null : outcome;
}
Insert cell
partyColor = d => (d.party === "D" ? colorD : d.party === "R" ? colorR : "#888")
Insert cell
colorD = "#2a72c9"
Insert cell
colorR = "#c92a2a"
Insert cell
prunedOpacity = 0.05
Insert cell
normalOpacity = 0.3
Insert cell
fullOpacity = 1.0
Insert cell
strokeOpacity = (pruned, highlight) =>
pruned ? prunedOpacity : highlight ? fullOpacity : normalOpacity
Insert cell
stateLabel = d => (width > 800 ? d.name : d.shortname)
Insert cell
candidateD = "Biden"
Insert cell
candidateR = "Trump"
Insert cell
import { form } from "@mbostock/form-input"
Insert cell
d3 = require("d3@6")
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