Published
Edited
Oct 27, 2020
Importers
2 stars
Insert cell
Insert cell
confidenceOrder = ['Closed', 'Uncontested', 'Safe', 'Likely', 'Lean', 'Tilt', 'Toss-Up', 'Open']
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
md`
## # % candidates that raised more and won 2018 election
`
Insert cell
nineDistricts = _.chain(texas2020).sortBy(d => -d.voterPower).take(9).value()
Insert cell
_.sumBy(nineDistricts, d => _.sumBy(d.pending, d => _.includes(["D", "R"], d.party) ? d.total$ : 0))
Insert cell
generalElection2018 = _.filter(FTM2018, d => d.detailedStatus.includes('GENERAL'))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
_.chain(generalElection2018)
.groupBy('office')
.filter(candidates => candidates.length > 1)
.map(candidates => {
const won = _.find(candidates, d => d.status === 'WON')
if (won.incumbent || won.open) return
console.log(won)
const max = _.maxBy(candidates, d => d.total$)
return won === max
}).filter().countBy()
.value()
Insert cell
Insert cell
FTM2018 = cleanFTM(await d3.csv(`https://docs.google.com/spreadsheets/d/1BHRitvRqsS2pIl1Bft8-Mr6VgqYFB0I36xu1WQwsMjc/gviz/tq?tqx=out:csv&sheet=Texas FTM 2018`))
Insert cell
texas2020 = {
const moneyball = cleanMoneyball(await d3.csv(`https://docs.google.com/spreadsheets/d/1BHRitvRqsS2pIl1Bft8-Mr6VgqYFB0I36xu1WQwsMjc/gviz/tq?tqx=out:csv&sheet=Texas Moneyball 2020`))
const FTM = cleanFTM(await d3.csv(`https://docs.google.com/spreadsheets/d/1BHRitvRqsS2pIl1Bft8-Mr6VgqYFB0I36xu1WQwsMjc/gviz/tq?tqx=out:csv&sheet=Texas FTM 2020`))
return _.chain(FTM)
.union(_.filter(FTM2018, d => d.legislature === 'SD'))
.groupBy('office')
.map((candidates, office) => {
const [,legislature] = office.split('-')
const pending = _.filter(candidates, d => d.status === 'PENDING')
const won = _.filter(candidates, d => d.status === 'WON')
// join with princeton dataset
let money = _.find(moneyball, d => d.office === office)
if (!money) {
const between = pending.length ? pending : won
const incumbent = _.find(between, 'incumbent')
const favored = _.find(between, d => _.includes(['D', 'R'], d.party))
money = {
office, confidence: pending.length ? 'Uncontested' : 'Closed',
incumbent: incumbent ? incumbent.party : 'Open',
favored: favored.party,
}
}
return Object.assign(money, {legislature, candidates, pending})
})
.value()
}
Insert cell
cleanFTM = (data) => {
return _.chain(data)
.filter(d => d['Election Type'] === 'STANDARD')
.map(d => {
const [leg,, district] = d['Office Sought'].split(' ')
const legislature = `${leg[0]}D`
const office = `TX-${legislature}-${+district}`

return {
office, legislature, candidate: d.Candidate,
party: d['General Party'][0],
status: d['Status of Candidate'],
detailedStatus: d['Election Status'],
incumbent: d['Incumbency Status'] === 'INCUMBENT',
open: d['Incumbency Status'] === 'OPEN',
total$: +(d['Total $'].replace(/[$\,]/g, '')),
}
}).value()
}
Insert cell
cleanMoneyball = (data) => {
return _.map(data, d => {
return {
office: d.district,
confidence: d.confidence,
incumbent: d.incumbent,
favored: d.favored,
voterPower: +d.redistricting_voter_power,
}
})
}
Insert cell
d3 = require('d3')
Insert cell
_ = require('lodash')
Insert cell
import {vl} from '@vega/vega-lite-api'
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