Published
Edited
Aug 24, 2021
2 stars
Also listed in…
Political Issues
Insert cell
Insert cell
probability_map = {
let div = d3
.create("div")
.style("width", `${map_width}px`)
.style("height", `${height}px`)
.style("overflow", "hidden");

let svg = div
.append("svg")
.style("overflow", "hidden")
.attr("viewBox", [0, 0, map_width, height]);

let path = d3.geoPath().projection(proj);

let map = svg.append("g");
map
.selectAll("path")
.data(states.features)
.join("path")
.attr("class", "state")
.attr("d", path)
.style("fill", function (d) {
let abbr = d.properties.fips;
let dd = data.filter((o) => o.abbr == abbr);
let p;
if (dd.length > 0) {
p = parseFloat(data.filter((o) => o.abbr == abbr)[0]["pj"]);
} else {
// p = 0.5;
}
return d3.interpolateRdBu(p);
})
.style("fill-opacity", 0.7)
.attr("data-state", function (d, i) {
let abbr = d.properties.fips;
return abbr;
})
.attr("stroke-width", "1.5px")
.attr("stroke", "#ddd")
.attr("stroke-linejoin", "round")
.on("mouseenter", function (evt, d) {
// d3.selectAll('path').style('fill-opacity', 0.2);
d3.select(this).style("fill-opacity", 1);
})
.on("mouseleave", function (evt, d) {
d3.selectAll("path").style("fill-opacity", 0.7);
});

map
.selectAll("path")
.nodes()
.forEach(function (p) {
let abbr = d3.select(p).attr("data-state");
let info = data.filter((o) => o.abbr == abbr);
if (info.length > 0) {
info = info[0];
}
tippy(p, {
allowHTML: true,
content: `
<div>${info.state}</div>
<div>Biden: ${d3.format("0.2f")(100 * info.pj)}%</div>
<div>Trump: ${d3.format("0.2f")(100 * (1 - info.pj))}%</div>`
});
});

return div.node();
}
Insert cell
result_cnt = (covid_check, { runs: 0, biden: 0, trump: 0 })
Insert cell
Insert cell
Insert cell
result_map = html``
Insert cell
first_run = make_result_map(run_one())
Insert cell
function make_result_map(trial) {
let biden_count = 0;
let trump_count = 0;
trial.forEach(function(o) {
let r = o.result;
if (r == 'Trump') {
trump_count = trump_count + o.votes;
} else {
biden_count = biden_count + o.votes;
}
});
result_cnt.runs++;
if (biden_count > trump_count) {
result_cnt.biden++;
} else {
result_cnt.trump++;
}

let div = d3
.create('div')
.attr('class', 'result_container')
.style("width", `${map_width}px`)
.style("height", `${30 + height}px`)
.style('overflow', 'hidden');

let result_display = div
.append('div')
.style("width", `${map_width}px`)
.style('height', '30px')
.style('text-align', 'center')
.html(
`Biden: ${biden_count}, Trump: ${trump_count} <br /> Percentage of Biden wins: ${
result_cnt.biden
} /
${result_cnt.runs} = ${d3.format('0.2f')(
(100 * result_cnt.biden) / result_cnt.runs
)}%`
);

let svg = div
.append('svg')
.style('overflow', 'hidden')
.attr("viewBox", [0, 0, map_width, height]);

let path = d3.geoPath().projection(proj);

let map = svg.append('g');
map
.selectAll("path")
.data(states.features)
.join("path")
.attr('class', 'state')
.attr('d', path)
.style("fill", function(d) {
let abbr = d.properties.fips;
let dd = trial.filter(o => o.abbr == abbr);
let p;
if (dd.length > 0 && dd[0].result == "Biden") {
p = 1;
} else {
p = 0;
}
return d3.interpolateRdBu(p);
})
.style('fill-opacity', 0.7)
.attr('data-state', function(d, i) {
let abbr = d.properties.fips;
return abbr;
})
.attr("stroke-width", '1.5px')
.attr("stroke", "#ddd")
.attr("stroke-linejoin", "round");
d3.selectAll('.result_container').remove();
d3.select(result_map).append(() => div.node());
}
Insert cell
function run_one(covid = false) {
let results = [];
let r, p;
if (covid) {
let c = Math.random();
if (c < 0.8) {
p = 2;
} else {
p = 1;
}
} else {
p = 1;
}
for (let i = 0; i < data.length; i++) {
let c = Math.random();
if (c < data[i].pj ** p) {
r = 'Biden';
} else {
r = 'Trump';
}
results.push(Object.assign({ result: r }, data[i]));
}
return results;
}
Insert cell
proj = d3
.geoIdentity()
.reflectY(true)
.fitSize([map_width, height], states)
Insert cell
map_width = 0.75 * width
Insert cell
height = 0.625 * map_width
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
data = {
let data = await FileAttachment(
"fivethirtyeight_electoral_probabilities@1.csv"
).csv();
data.forEach(o => {
o.pj = parseFloat(o.pj);
o.votes = parseInt(o.votes);
});
return data;
}
Insert cell
states = {
let map_file = await FileAttachment("states.json").json();
let states = topojson.feature(map_file, map_file.objects.states);
return states;
}
Insert cell
import { button, checkbox } from "@jashkenas/inputs"
Insert cell
topojson = require("topojson-client@3")
Insert cell
tippy = require("tippy.js@6")
Insert cell
d3 = require('d3@6')
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