Skip to content

Instantly share code, notes, and snippets.

@zackmdavis
Created November 8, 2020 01:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zackmdavis/623e15a3cdab66d3eaecf2a6f8b6169a to your computer and use it in GitHub Desktop.
Save zackmdavis/623e15a3cdab66d3eaecf2a6f8b6169a to your computer and use it in GitHub Desktop.
logarithmic scores for state-by-state predictions of U.S. presidential election 2020
from math import log2
from collections import namedtuple
StateResult = namedtuple(
"StateResult",
["state", "economist", "fivethirtyeight", "predictit", "actual"],
)
state_results = [
StateResult(
"AK",
economist=0.0385,
fivethirtyeight=0.1496,
predictit=0.11,
actual=False,
),
StateResult(
"AL",
economist=0,
fivethirtyeight=0.015825,
predictit=0.02,
actual=False,
),
StateResult(
"AR",
economist=0,
fivethirtyeight=0.00965,
predictit=0.02,
actual=False,
),
StateResult(
"AZ",
economist=0.7111875,
fivethirtyeight=0.680375,
predictit=0.52,
actual=True,
),
StateResult(
"CA",
economist=1,
fivethirtyeight=0.9985,
predictit=0.94,
actual=True,
),
StateResult(
"CO",
economist=0.9985625,
fivethirtyeight=0.968775,
predictit=0.90,
actual=True,
),
StateResult(
"CT",
economist=1,
fivethirtyeight=0.999325,
predictit=0.93,
actual=True,
),
StateResult(
"DC",
economist=1,
fivethirtyeight=1,
predictit=0.96,
actual=True,
),
StateResult(
"DE",
economist=1,
fivethirtyeight=0.99995,
predictit=0.94,
actual=True,
),
StateResult(
"FL",
economist=0.7855625,
fivethirtyeight=0.684175,
predictit=0.43,
actual=False,
),
StateResult(
"GA",
economist=0.569,
fivethirtyeight=0.576525,
predictit=0.40,
actual=True,
),
StateResult(
"HI",
economist=1,
fivethirtyeight=0.993575,
predictit=0.94,
actual=True,
),
StateResult(
"IA",
economist=0.3920625,
fivethirtyeight=0.399975,
predictit=0.26,
actual=False,
),
StateResult(
"ID",
economist=0,
fivethirtyeight=0.00565,
predictit=0.02,
actual=False,
),
StateResult(
"IL",
economist=1,
fivethirtyeight=0.999275,
predictit=0.94,
actual=True,
),
StateResult(
"IN",
economist=0.00025,
fivethirtyeight=0.03475,
predictit=0.05,
actual=False,
),
StateResult(
"KS",
economist=0.000875,
fivethirtyeight=0.014875,
predictit=0.04,
actual=False,
),
StateResult(
"KY",
economist=0,
fivethirtyeight=0.01465,
predictit=0.03,
actual=False,
),
StateResult(
"LA",
economist=0.00075,
fivethirtyeight=0.02825,
predictit=0.02,
actual=False,
),
StateResult(
"MA",
economist=1,
fivethirtyeight=0.9996,
predictit=0.95,
actual=True,
),
StateResult(
"MD",
economist=1,
fivethirtyeight=0.999625,
predictit=0.94,
actual=True,
),
StateResult(
"ME",
economist=0.999,
fivethirtyeight=0.903975,
predictit=0.87,
actual=True,
),
StateResult(
"MI",
economist=0.9785625,
fivethirtyeight=0.94515,
predictit=0.69,
actual=True,
),
StateResult(
"MN",
economist=0.9868125,
fivethirtyeight=0.9577,
predictit=0.74,
actual=True,
),
StateResult(
"MO",
economist=0.0143125,
fivethirtyeight=0.063525,
predictit=0.06,
actual=False,
),
StateResult(
"MS",
economist=0.0018125,
fivethirtyeight=0.08425,
predictit=0.06,
actual=False,
),
StateResult(
"MT",
economist=0.0109375,
fivethirtyeight=0.177725,
predictit=0.14,
actual=False,
),
StateResult(
"NC",
economist=0.670875,
fivethirtyeight=0.6369,
predictit=0.46,
actual=False,
),
StateResult(
"ND",
economist=0,
fivethirtyeight=0.023825,
predictit=0.03,
actual=False,
),
StateResult(
"NE",
economist=0.0000625,
fivethirtyeight=0.005675,
predictit=0.04,
actual=False,
),
StateResult(
"NH",
economist=0.982625,
fivethirtyeight=0.891425,
predictit=0.73,
actual=True,
),
StateResult(
"NJ",
economist=1,
fivethirtyeight=0.99245,
predictit=0.94,
actual=True,
),
StateResult(
"NM",
economist=0.99725,
fivethirtyeight=0.977,
predictit=0.88,
actual=True,
),
StateResult(
"NV",
economist=0.9473125,
fivethirtyeight=0.8774,
predictit=0.74,
actual=True,
),
StateResult(
"NY",
economist=1,
fivethirtyeight=0.99995,
predictit=0.93,
actual=True,
),
StateResult(
"OH",
economist=0.4134375,
fivethirtyeight=0.4512,
predictit=0.29,
actual=False,
),
StateResult(
"OK",
economist=0,
fivethirtyeight=0.006025,
predictit=0.03,
actual=False,
),
StateResult(
"OR",
economist=1,
fivethirtyeight=0.9817,
predictit=0.92,
actual=True,
),
StateResult(
"PA",
economist=0.9428125,
fivethirtyeight=0.840575,
predictit=0.61,
actual=True,
),
StateResult(
"RI",
economist=1,
fivethirtyeight=0.9992,
predictit=0.95,
actual=True,
),
StateResult(
"SC",
economist=0.01625,
fivethirtyeight=0.09955,
predictit=0.25,
actual=False,
),
StateResult(
"SD",
economist=0,
fivethirtyeight=0.05045,
predictit=0.05,
actual=False,
),
StateResult(
"TN",
economist=0,
fivethirtyeight=0.031775,
predictit=0.04,
actual=False,
),
StateResult(
"TX",
economist=0.283,
fivethirtyeight=0.38235,
predictit=0.30,
actual=False,
),
StateResult(
"UT",
economist=0.0000625,
fivethirtyeight=0.0462,
predictit=0.06,
actual=False,
),
StateResult(
"VA",
economist=0.9975,
fivethirtyeight=0.99015,
predictit=0.89,
actual=True,
),
StateResult(
"VT",
economist=1,
fivethirtyeight=0.996075,
predictit=0.95,
actual=True,
),
StateResult(
"WA",
economist=1,
fivethirtyeight=0.99185,
predictit=0.94,
actual=True,
),
StateResult(
"WI",
economist=0.97425,
fivethirtyeight=0.942225,
predictit=0.70,
actual=True,
),
StateResult(
"WV",
economist=0,
fivethirtyeight=0.0076,
predictit=0.03,
actual=False,
),
StateResult(
"WY",
economist=0,
fivethirtyeight=0.00165,
predictit=0.02,
actual=False,
),
]
def is_swinglike(state_result):
swing_calls = [
0.1 < getattr(state_result, predictor) < 0.9
for predictor in ["fivethirtyeight", "economist", "predictit"]
]
return sum(swing_calls) >= 2
def score():
scores = {"fivethirtyeight": 0, "economist": 0, "predictit": 0}
swinglike_only_scores = {
"fivethirtyeight": 0,
"economist": 0,
"predictit": 0,
}
losses = {}
print(
"{} states are swinglike".format(
sum([is_swinglike(sr) for sr in state_results])
)
)
for state_result in state_results:
if state_result.actual is None:
continue
for predictor in scores.keys():
if state_result.actual: # Biden win
probability = getattr(state_result, predictor)
else:
probability = 1 - getattr(state_result, predictor)
subscore = log2(probability)
scores[predictor] += subscore
if is_swinglike(state_result):
swinglike_only_scores[predictor] += subscore
losses[(predictor, state_result.state)] = subscore
return scores, swinglike_only_scores, losses
if __name__ == "__main__":
scores, swinglike_only_scores, losses = score()
print(sorted(scores.items(), key=lambda e: e[1]))
print(sorted(swinglike_only_scores.items(), key=lambda e: e[1]))
print(sorted(losses.items(), key=lambda e: e[1])[:10])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment