Recipes¶
Useful Elex patterns. Contribute your own.
All examples specify a data file instead of a live or test election date
so that all examples can be followed even if you don’t have an AP API key.
For real election data, replace -d FILENAME
in these examples with an
election date.
Get results at a specific level¶
Get only state level results:
elex results --results-level state -d "${VIRTUAL_ENV}/src/elex/tests/data/20160301_super_tuesday.json"
id | raceid | racetype | racetypeid | ballotorder | candidateid | description | delegatecount | electiondate | fipscode | first | incumbent | initialization_data | is_ballot_measure | last | lastupdated | level | national | officeid | officename | party | polid | polnum | precinctsreporting | precinctsreportingpct | precinctstotal | reportingunitid | reportingunitname | runoff | seatname | seatnum | statename | statepostal | test | uncontested | votecount | votepct | winner |
24547-polid-8639-state-1 | 24547 | Primary | R | 2 | 33360 | 0 | 2016-03-01 | Donald | False | False | False | Trump | 2016-03-02T20:35:54Z | state | True | P | President | GOP | 8639 | 27533 | 2172 | 0.9995 | 2173 | state-1 | False | Massachusetts | MA | False | False | 311313 | 0.493056 | True | |||||
24547-polid-36679-state-1 | 24547 | Primary | R | 13 | 33366 | 0 | 2016-03-01 | John | False | False | False | Kasich | 2016-03-02T20:35:54Z | state | True | P | President | GOP | 36679 | 27528 | 2172 | 0.9995 | 2173 | state-1 | False | Massachusetts | MA | False | False | 113783 | 0.180209 | False | |||||
… |
To cut down on load and bandwidth use and speed up loading when you are repeatedly loading results, specify only the level(s) you need to display.
Add timestamp or batch name column to any data command¶
You can add a timestamp column to track results (or any other
data output by elex) with the --with-timestamp
flag).
elex elections --with-timestamp -d "${VIRTUAL_ENV}/elex-dev/src/elex/tests/data/00000000_elections.json"
id | electiondate | liveresults | testresults | timestamp |
2012-03-13 | 2012-03-13 | True | False | 1460438301 |
2012-11-06 | 2012-11-06 | True | False | 1460438301 |
… |
If you prefer, you can set a batch name. This is useful when executing multiple commands that need a single grouping column.
elex elections --batch-name batch-031 -d "${VIRTUAL_ENV}/elex-dev/src/elex/tests/data/00000000_elections.json"
id | electiondate | liveresults | testresults | timestamp |
2016-02-23 | 2016-02-23 | True | False | batch-031 |
2016-02-27 | 2016-02-27 | True | False | batch-031 |
… |
Get local election results¶
Get only local races:
elex races 03-15-16 --local-only -d "${VIRTUAL_ENV}/src/elex/tests/data/20160301_super_tuesday.json"
id | raceid | racetype | racetypeid | description | electiondate | initialization_data | is_ballot_measure | lastupdated | national | officeid | officename | party | seatname | seatnum | statename | statepostal | test | uncontested |
14897 | 14897 | Primary | R | 2016-03-15 | True | False | 2016-03-18T12:29:42Z | True | 0 | State’s Attorney | GOP | Cook County | IL | False | True | |||
15329 | 15329 | Primary | D | 2016-03-15 | True | False | 2016-03-18T12:29:42Z | True | 0 | Recorder of Deeds | Dem | Cook County | IL | False | True | |||
… |
Get only local results:
elex results --local-only
Get AP zero count data¶
AP’s set zero count parameter is a special server feature that only makes sense to query live.
elex results 03-15-16 --set-zero-counts
id | raceid | racetype | racetypeid | ballotorder | candidateid | description | delegatecount | electiondate | fipscode | first | incumbent | initialization_data | is_ballot_measure | last | lastupdated | level | national | officeid | officename | party | polid | polnum | precinctsreporting | precinctsreportingpct | precinctstotal | reportingunitid | reportingunitname | runoff | seatname | seatnum | statename | statepostal | test | uncontested | votecount | votepct | winner |
10673-polid-8639-state-1 | 10673 | Primary | R | 13 | 20428 | 0 | 2016-03-15 | Donald | False | False | False | Trump | 2016-03-16T21:05:09Z | state | True | P | President | GOP | 8639 | 14574 | 0 | 0.0 | 5810 | state-1 | False | Florida | FL | False | False | 0 | 0.0 | False | |||||
… |
Auto-generate SQL schemas with csvkit¶
Install csvkit, a handy tool for working with CSVs.
Now build the results schema by using the candidate-reporting-units
command.
elex candidate-reporting-units -d "${VIRTUAL_ENV}/src/elex/tests/data/20160301_super_tuesday.json" | csvsql --tables results -i sqlite
2016-04-14 00:51:07,675 (INFO) elex (v2.0.0) : Getting candidate reporting units for election 2016-03-26
CREATE TABLE results (
id VARCHAR(23) NOT NULL,
raceid INTEGER NOT NULL,
racetype VARCHAR(6) NOT NULL,
racetypeid VARCHAR(1) NOT NULL,
ballotorder INTEGER NOT NULL,
candidateid INTEGER NOT NULL,
description VARCHAR(32),
delegatecount INTEGER NOT NULL,
electiondate DATE NOT NULL,
fipscode VARCHAR(32),
first VARCHAR(7),
incumbent BOOLEAN NOT NULL,
initialization_data BOOLEAN NOT NULL,
is_ballot_measure BOOLEAN NOT NULL,
last VARCHAR(12) NOT NULL,
lastupdated DATETIME NOT NULL,
level VARCHAR(32),
national BOOLEAN NOT NULL,
officeid VARCHAR(1) NOT NULL,
officename VARCHAR(9) NOT NULL,
party VARCHAR(3) NOT NULL,
polid INTEGER NOT NULL,
polnum INTEGER NOT NULL,
precinctsreporting INTEGER NOT NULL,
precinctsreportingpct FLOAT NOT NULL,
precinctstotal INTEGER NOT NULL,
reportingunitid VARCHAR(32),
reportingunitname VARCHAR(32),
runoff BOOLEAN NOT NULL,
seatname VARCHAR(32),
seatnum VARCHAR(32),
statename VARCHAR(10) NOT NULL,
statepostal VARCHAR(2) NOT NULL,
test BOOLEAN NOT NULL,
uncontested BOOLEAN NOT NULL,
votecount INTEGER NOT NULL,
votepct FLOAT NOT NULL,
winner BOOLEAN NOT NULL,
CHECK (incumbent IN (0, 1)),
CHECK (initialization_data IN (0, 1)),
CHECK (is_ballot_measure IN (0, 1)),
CHECK (national IN (0, 1)),
CHECK (runoff IN (0, 1)),
CHECK (test IN (0, 1)),
CHECK (uncontested IN (0, 1)),
CHECK (winner IN (0, 1))
);
Insert results with csvkit + sqlite¶
This is not a wildly efficient way to get results into a database, but it is lightweight.
elex candidate-reporting-units -d "${VIRTUAL_ENV}/src/elex/tests/data/20160301_super_tuesday.json" | csvsql --tables results --db sqlite:///db.sqlite --insert
Filter with jq and upload to S3¶
This recipe uses the jq json filtering tool to create a national results json data file with a limited set of data fields and the AWS cli tools to upload the filtered json to S3.
Requirements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/bin/bash
# S3 url: MUST be set to your bucket and path.
ELEX_S3_URL='mybucket.tld/output/path.json'
# Get results and upload to S3
elex results 2012-11-06 --results-level state -o json \
| jq -c '[
.[] |
select(.level == "state" ) |
select(.officename == "President") |
{
officename: .officename,
statepostal: .statepostal,
first: .first,
last: .last,
party: .party,
votecount: .votecount,
votepct: .votepct,
winner: .winner,
level: .level
}
]' \
| gzip -vc \
| aws s3 cp - s3://$ELEX_S3_URL \
--acl public-read \
--content-type=application/json \
--content-encoding gzip
# Check response headers
curl -I $ELEX_S3_URL
# Get first entry of uploaded json
curl -s --compressed $ELEX_S3_URL | jq '[.[]][0]'
|
ELEX_S3_URL
must be set to your s3 bucket and path.
Steps:
- Get election results in json format with
elex
- Pipe results to
jq
for filtering - Pipe filtered results to
gzip
to compress - Pipe gzipped results to
aws s3 cp
to send to S3.
Inspect with an ORM using Flask and Peewee¶
This recipe uses the Flask web framework and the Peewee Python ORM to model, query and update data that elex
provides.
Requirements:
- Elex loader, an NYT project that calls
elex
to load data into a Postgres database with CSV and the PostgresCOPY
command. - Elex admin, an NYT project that is a simple, web-based admin for creating and editing data to override AP election results, including candidate names, race descriptions, and race calls.
Steps:
- Install
elex-loader
using the loader instructions. - Install
elex-admin
using the admin instructions.
Extra steps:
- Use the
models.py
that come withelex-admin
to query data.