Add files via upload
This commit is contained in:
1 parent
58b380c511
commit
75503b8b23
2 files changed
+1432
-114
No files matched your search
+149
-114
@@ -8,7 +8,7 @@
|
||||
"\n",
|
||||
"# Tracking Trump: Electoral Votes Edition\n",
|
||||
"\n",
|
||||
"[538](https://projects.fivethirtyeight.com/trump-approval-ratings/) shows presidential approval ratings (currently about 42% (±4) approval and 53% (±4) disapproval). Do approval ratings predict election results? There are three big caveats:\n",
|
||||
"[RealClearPolitics](https://www.realclearpolitics.com/epolls/other/president_trump_job_approval-6179.html) and [538](https://projects.fivethirtyeight.com/trump-approval-ratings/) shows presidential approval ratings (currently about 43% approval and 53% disapproval for a net -10%). Do approval ratings predict election results? There are three big caveats:\n",
|
||||
"\n",
|
||||
"1. These are approval polls, not votes. \n",
|
||||
"\n",
|
||||
@@ -16,8 +16,9 @@
|
||||
"\n",
|
||||
"3. These are popular votes, not electoral votes. \n",
|
||||
"\n",
|
||||
"We can't be conclusive about the first two points, but this notebook can take the state-by-state, month-by-month approval data from Morning Consult's\n",
|
||||
"[Tracking Trump](https://morningconsult.com/tracking-trump/) web page and compute electoral votes, under the assumption that Trump wins the electoral votes of states he has positive net approval (and for the purposes of computation we'll assign half the electoral votes for states where approval exactly equals disapproval).\n",
|
||||
"We can't be conclusive about the first two points, but this notebook can take the \n",
|
||||
"\n",
|
||||
"and compute electoral votes, under the assumption that Trump wins the electoral votes of states he has positive net approval (and for the purposes of computation we'll assign half the electoral votes for states where approval exactly equals disapproval).\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# TL;DR for policy wonks\n",
|
||||
@@ -36,13 +37,14 @@
|
||||
"\n",
|
||||
"- **Movement**: What's the most a state's net approval could be expected to move, due to random fluctuations (that is, assuming there is no big event that changes people's minds)? I define the maximum expected **movement** of a state as 1/5 of the undecided voters (i.e. assume the undecided voters broke 60/40 one way or the other) plus 2 standard deviations in the net approval over the last 12 months. \n",
|
||||
"\n",
|
||||
"- **Swing state**: I define a swing state as one whose maximum expected movement is greater than the absolute value of the net approval. There are 15 such states now. (My definition correlates well with the standard wisdom on swing states, but with a few surprises, such as North Dakota, where Trump is currently only +1% net approval. My model does not count Pennsylvania, Michigan, and Wisconsin as swing states, because Trump is currently -7%, -12% and -13% respectively, and expected movement is low at 3% to 5%.) If Trump won all the swing states he would get **253** electoral votes, and if he lost them all, **76** electoral votes.\n",
|
||||
"- **Swing state**: I define a swing state as one whose maximum expected movement is greater than the absolute value of the net approval. There are 15 such states now. My definition correlates well with the standard wisdom on swing states, but with a few surprises: North Dakota is included because Trump is currently only +1% net approval; a typical Republican is +30%. My model says that Pennsylvania, Michigan, and Wisconsin, which are traditionally considered swing states, are currently out of reach for Trump because they have low movement (3% to 5%) and Trump is currently at -7%, -12% and -13% respectively. If Trump won all the swing states he would get **253** electoral votes, and if he lost them all, **76** electoral votes.\n",
|
||||
"\n",
|
||||
"- **Margin**: Suppose a future event swings voters in one direction or another uniformly, across the board in all states. How much of a swing would be necessary to change the election outcome? We call that the **margin**. Today **Trump's margin is 7%:** if he got 7% more votes in all states he would be over 270 electoral votes. (This could come, for example, by convincing undecided voters to break for him at a 2% to 1% ratio, and then convincing 3% of disapproving voters to switch to approving.)\n",
|
||||
"- **Margin**: Suppose a future event swings voters in one direction or another uniformly, across the board in all states. How much of a swing would be necessary to change the election outcome? We call that the **margin**. Today **Trump's margin is 7%:** if he got 7% more votes in all states he would be over 270 electoral votes. (This could come, for example, by convincing the 3% of undecided voters to break for him at a 2% to 1% ratio, and then convincing 3% of disapproving voters to switch to approving.)\n",
|
||||
"\n",
|
||||
"# Data and Code\n",
|
||||
"\n",
|
||||
"First fetch the [Tracking Trump](https://morningconsult.com/tracking-trump/) web page and cache it locally: "
|
||||
"First fetch the state-by-state, month-by-month approval data from Morning Consult's\n",
|
||||
"[Tracking Trump](https://morningconsult.com/tracking-trump/) web page and cache it locally: "
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -56,7 +58,7 @@
|
||||
"text": [
|
||||
" % Total % Received % Xferd Average Speed Time Time Time Current\n",
|
||||
" Dload Upload Total Spent Left Speed\n",
|
||||
"100 116k 0 116k 0 0 193k 0 --:--:-- --:--:-- --:--:-- 193k\n"
|
||||
"100 116k 0 116k 0 0 234k 0 --:--:-- --:--:-- --:--:-- 234k\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -68,7 +70,7 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now define the code. Note that `data` contains the [electoral votes by state](https://www.britannica.com/topic/United-States-Electoral-College-Votes-by-State-1787124) and the [partisan lean by state](https://github.com/fivethirtyeight/data/tree/master/partisan-lean) (how much more Republican (plus) or Democratic (minus) leaning the state is compared to the country as a whole, across multiple recent elections), and `net_usa` has the [country-wide net presidential approval](https://projects.fivethirtyeight.com/trump-approval-ratings/)."
|
||||
"Now some imports: "
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -83,8 +85,22 @@
|
||||
"import ast\n",
|
||||
"from collections import namedtuple\n",
|
||||
"from IPython.display import display, Markdown\n",
|
||||
"from statistics import stdev\n",
|
||||
"\n",
|
||||
"from statistics import stdev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Additional data: the variable `data` contains the [electoral votes by state](https://www.britannica.com/topic/United-States-Electoral-College-Votes-by-State-1787124) and the [partisan lean by state](https://github.com/fivethirtyeight/data/tree/master/partisan-lean) (how much more Republican (plus) or Democratic (minus) leaning the state is compared to the country as a whole, across multiple recent elections). The variable `net_usa` has the [country-wide net presidential approval](https://projects.fivethirtyeight.com/trump-approval-ratings/) by month."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"data = { # From https://github.com/fivethirtyeight/data/tree/master/partisan+lean \n",
|
||||
" # a dict of {\"state name\": (electoral_votes, partisan_lean)}\n",
|
||||
" \"Alabama\": (9, +27), \"Alaska\": (3, +15), \"Arizona\": (11, +9), \n",
|
||||
@@ -113,11 +129,25 @@
|
||||
" '1-Feb-18': -15, '1-Mar-18': -14, '1-Apr-18': -13, '1-May-18': -12,\n",
|
||||
" '1-Jun-18': -11, '1-Jul-18': -10, '1-Aug-18': -12, '1-Sep-18': -14,\n",
|
||||
" '1-Oct-18': -11, '1-Nov-18': -11, '1-Dec-18': -10, '1-Jan-19': -12,\n",
|
||||
" '1-Feb-19': -16, '1-Mar-19': -11, '1-Apr-19': -11, '1-May-19': -12}\n",
|
||||
"\n",
|
||||
"State = namedtuple('State', 'name, ev, lean, approvals, disapprovals')\n",
|
||||
"State.__doc__ = '''A State has a name, the number of electoral votes (.ev),\n",
|
||||
"the partisan lean (.lean) and two dicts of {date: percent}: .approvals and .disapprovals'''\n",
|
||||
" '1-Feb-19': -16, '1-Mar-19': -11, '1-Apr-19': -11, '1-May-19': -12}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now the code to parse and manipulate the data:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class State(namedtuple('_', 'name, ev, lean, approvals, disapprovals')):\n",
|
||||
" '''A State has a name, the number of electoral votes (.ev), the partisan lean (.lean) \n",
|
||||
" and two dicts of {date: percent}: .approvals and .disapprovals'''\n",
|
||||
"\n",
|
||||
"def parse_page(filename='evs.html', data=data):\n",
|
||||
" \"Read data from the file and return (list of dates, list of `State`s, last date).\"\n",
|
||||
@@ -138,12 +168,12 @@
|
||||
"\n",
|
||||
"assert len(states) == 51 and sum(s.ev for s in states) == 538\n",
|
||||
"\n",
|
||||
"def EV(states, date=now, swing=0):\n",
|
||||
"def EV(states, date=now, swing=0) -> int:\n",
|
||||
" \"Total electoral votes with net positive approval (plus half the votes for net zero).\"\n",
|
||||
" return sum(s.ev * (1/2 if net(s, date) + swing == 0 else int(net(s, date) + swing > 0))\n",
|
||||
" for s in states)\n",
|
||||
"\n",
|
||||
"def margin(states, date=now):\n",
|
||||
"def margin(states, date=now) -> int:\n",
|
||||
" \"What's the least swing that would lead to a majority?\"\n",
|
||||
" return next(swing for swing in range(-50, 50) if EV(states, date, swing) >= 270)\n",
|
||||
"\n",
|
||||
@@ -151,9 +181,7 @@
|
||||
"def undecided(state, date=now): return 100 - state.approvals[date] - state.disapprovals[date]\n",
|
||||
"def movement(state, date=now): return undecided(state, date) / 5 + 2 * 𝝈(state)\n",
|
||||
"def 𝝈(state, recent=dates[-12:]): return stdev(net(state, d) for d in recent)\n",
|
||||
"def is_swing(state): return abs(net(state)) < movement(state)\n",
|
||||
"\n",
|
||||
"def md(lines): display(Markdown('\\n'.join(lines)))"
|
||||
"def is_swing(state) -> bool: return abs(net(state)) < movement(state)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -165,7 +193,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -174,7 +202,7 @@
|
||||
"193.0"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -185,7 +213,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -194,7 +222,7 @@
|
||||
"7"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -205,7 +233,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -223,7 +251,7 @@
|
||||
" 9: 288.0}"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -254,12 +282,12 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 648x432 with 1 Axes>"
|
||||
]
|
||||
@@ -278,9 +306,9 @@
|
||||
" N = len(dates)\n",
|
||||
" err = [[EV(states, date) - EV(states, date, -swing) for date in dates],\n",
|
||||
" [EV(states, date, swing) - EV(states, date) for date in dates]]\n",
|
||||
" plt.plot(range(N), [270] * N, color='darkorange', label=\"270\")\n",
|
||||
" plt.errorbar(range(N), [EV(states, date) for date in dates], fmt='D-',\n",
|
||||
" yerr=err, ecolor='grey', capsize=7, label='EVs ±3% swing')\n",
|
||||
" plt.plot(range(N), [270] * N, color='darkorange', label=\"270\")\n",
|
||||
" labels('Months into term', 'Electoral Votes with Net Positive Approval')\n",
|
||||
" \n",
|
||||
"plot1(states, dates)"
|
||||
@@ -292,17 +320,17 @@
|
||||
"source": [
|
||||
"# Margin and country-wide net approval by month\n",
|
||||
"\n",
|
||||
"The next plot gives the swing margin needed to reach 270 for each month, along with the country-wide net approval. Trump has been in negative territory on all metrics since his fourth month in office. We see that the state-by-state margin roughly correlates with the country-wide net approval, but not exactly."
|
||||
"The next plot gives the swing margin needed to reach 270 for each month, along with the country-wide net approval. Trump has been in negative territory on all metrics since his fourth month in office. He's been net -10% or worse every month since his third in office. His necessary margin has been 4% or worse every month since his seventh. We see that the state-by-state margin roughly correlates with the country-wide net approval, but not exactly."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 648x432 with 1 Axes>"
|
||||
]
|
||||
@@ -315,8 +343,8 @@
|
||||
"def plot2(states, dates):\n",
|
||||
" N = len(dates)\n",
|
||||
" plt.plot(range(N), [0] * N, label='Net zero', color='darkorange')\n",
|
||||
" plt.plot(range(N), [-margin(states, date) for date in dates], 'o-', label='Margin')\n",
|
||||
" plt.plot(range(N), [net_usa[date] for date in dates], 'D-', label='Country-wide Net')\n",
|
||||
" plt.plot(range(N), [-margin(states, date) for date in dates], 'D-', label='Margin')\n",
|
||||
" plt.plot(range(N), [net_usa[date] for date in dates], 'go-', label='Country-wide Net')\n",
|
||||
" labels('Months into term', 'Net popularity')\n",
|
||||
" \n",
|
||||
"plot2(states, dates)"
|
||||
@@ -334,7 +362,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -381,9 +409,12 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def header(head): return head + '\\n' + '-'.join('|' * head.count('|'))\n",
|
||||
"def header(head) -> str: return head + '\\n' + '-'.join('|' * head.count('|'))\n",
|
||||
"\n",
|
||||
"def monthly(states, dates=reversed(dates)):\n",
|
||||
"def markdown(fn) -> str: return lambda *args: display(Markdown('\\n'.join(fn(*args))))\n",
|
||||
"\n",
|
||||
"@markdown\n",
|
||||
"def by_month(states, dates=reversed(dates)):\n",
|
||||
" yield header('|Month|EVs|Margin|Country|Undecided|')\n",
|
||||
" for date in dates:\n",
|
||||
" month = date.replace('1-', '').replace('-', ' 20')\n",
|
||||
@@ -391,7 +422,7 @@
|
||||
" f'|{sum(s.ev * undecided(s, date) for s in states) / 538:.0f}% '\n",
|
||||
" f'({sum(undecided(s, date) > 5 for s in states)})|')\n",
|
||||
" \n",
|
||||
"md(monthly(states))"
|
||||
"by_month(states)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -402,14 +433,14 @@
|
||||
"\n",
|
||||
"Below is each state sorted by net approval, with the state's maximum expected movement, and electoral vote allotment, followed by the cumulative running total of electoral votes and the percentages of approval, disapprovalsaproval, and undecided, and finally the standard deviation of the net approval over the last 12 months. By going down the **Total** column, you can see what it takes to win. \n",
|
||||
"\n",
|
||||
"The **bold state names** are the **swing states**, which I define as states in which the absolute value of net approval is less than two standard deviations of the net approval over time, plus a fifth of the undecided voters. The idea is that if we are just dealing with random sampling variation, you could expect future approval to be within two standard deviations 95% of the time, and if the undecideds split 60/40, then a candidate could get a net fifth of them. So it would be very unusual for the non-bold states to flip, unless some events change perception of the candidates.\n",
|
||||
"The **CAPITALIZED bold state names** are the **swing states**, which I define as states in which the absolute value of net approval is less than two standard deviations of the net approval over time, plus a fifth of the undecided voters. The idea is that if we are just dealing with random sampling variation, you could expect future approval to be within two standard deviations 95% of the time, and if the undecideds split 60/40, then a candidate could get a net fifth of them. So it would be very unusual for the non-bold states to flip, unless some events change perception of the candidates.\n",
|
||||
"\n",
|
||||
"This analysis says that if we consider all and only the bold swing states to be in play, then the total electoral votes for Trump could be anywhere in the range of 76 (if he lost them all) to 253 (if he won them all). It would take winning every single one of the swing states plus a three-standard deviation swing in Pennsylvania for Trump to reach 273.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@@ -428,21 +459,21 @@
|
||||
"|South Carolina|+10%|5%|9|63|53%|43%|4%|2.1%|\n",
|
||||
"|Oklahoma|+9%|8%|7|70|52%|43%|5%|3.5%|\n",
|
||||
"|Arkansas|+8%|7%|6|76|52%|44%|4%|3.0%|\n",
|
||||
"|**Missouri**|**+6%**|**7%**|10|86|51%|45%|4%|3.0%|\n",
|
||||
"|**South Dakota**|**+6%**|**10%**|3|89|51%|45%|4%|4.5%|\n",
|
||||
"|**Indiana**|**+3%**|**5%**|11|100|49%|46%|5%|2.0%|\n",
|
||||
"|**Montana**|**+3%**|**7%**|3|103|50%|47%|3%|3.4%|\n",
|
||||
"|**Texas**|**+3%**|**6%**|38|141|49%|46%|5%|2.7%|\n",
|
||||
"|**Nebraska**|**+2%**|**6%**|5|146|49%|47%|4%|2.8%|\n",
|
||||
"|**Utah**|**+2%**|**8%**|6|152|49%|47%|4%|3.6%|\n",
|
||||
"|**Georgia**|**+1%**|**7%**|16|168|48%|47%|5%|2.9%|\n",
|
||||
"|**Kansas**|**+1%**|**7%**|6|174|48%|47%|5%|3.0%|\n",
|
||||
"|**North Dakota**|**+1%**|**8%**|3|177|48%|47%|5%|3.3%|\n",
|
||||
"|**Alaska**|**+0%**|**12%**|3|180|47%|47%|6%|5.5%|\n",
|
||||
"|**Florida**|**+0%**|**7%**|29|209|48%|48%|4%|3.1%|\n",
|
||||
"|**North Carolina**|**-4%**|**6%**|15|224|46%|50%|4%|2.4%|\n",
|
||||
"|**Ohio**|**-4%**|**6%**|18|242|46%|50%|4%|2.4%|\n",
|
||||
"|**Arizona**|**-6%**|**8%**|11|253|45%|51%|4%|3.4%|\n",
|
||||
"|**MISSOURI**|**+6%**|**7%**|10|86|51%|45%|4%|3.0%|\n",
|
||||
"|**SOUTH DAKOTA**|**+6%**|**10%**|3|89|51%|45%|4%|4.5%|\n",
|
||||
"|**INDIANA**|**+3%**|**5%**|11|100|49%|46%|5%|2.0%|\n",
|
||||
"|**MONTANA**|**+3%**|**7%**|3|103|50%|47%|3%|3.4%|\n",
|
||||
"|**TEXAS**|**+3%**|**6%**|38|141|49%|46%|5%|2.7%|\n",
|
||||
"|**NEBRASKA**|**+2%**|**6%**|5|146|49%|47%|4%|2.8%|\n",
|
||||
"|**UTAH**|**+2%**|**8%**|6|152|49%|47%|4%|3.6%|\n",
|
||||
"|**GEORGIA**|**+1%**|**7%**|16|168|48%|47%|5%|2.9%|\n",
|
||||
"|**KANSAS**|**+1%**|**7%**|6|174|48%|47%|5%|3.0%|\n",
|
||||
"|**NORTH DAKOTA**|**+1%**|**8%**|3|177|48%|47%|5%|3.3%|\n",
|
||||
"|**ALASKA**|**+0%**|**12%**|3|180|47%|47%|6%|5.5%|\n",
|
||||
"|**FLORIDA**|**+0%**|**7%**|29|209|48%|48%|4%|3.1%|\n",
|
||||
"|**NORTH CAROLINA**|**-4%**|**6%**|15|224|46%|50%|4%|2.4%|\n",
|
||||
"|**OHIO**|**-4%**|**6%**|18|242|46%|50%|4%|2.4%|\n",
|
||||
"|**ARIZONA**|**-6%**|**8%**|11|253|45%|51%|4%|3.4%|\n",
|
||||
"|Virginia|-6%|4%|13|266|45%|51%|4%|1.8%|\n",
|
||||
"|Pennsylvania|-7%|3%|20|286|45%|52%|3%|1.4%|\n",
|
||||
"|Maine|-9%|8%|4|290|44%|53%|3%|3.9%|\n",
|
||||
@@ -478,90 +509,93 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"@markdown\n",
|
||||
"def by_state(states, d=now):\n",
|
||||
" total = 0\n",
|
||||
" yield header('|State|Net|Move|EV|Total|+|-|?|𝝈|')\n",
|
||||
" for s in sorted(states, key=net, reverse=True):\n",
|
||||
" total += s.ev\n",
|
||||
" b = '**' if is_swing(s) else ''\n",
|
||||
" yield (f'|{b}{s.name}{b}|{b}{net(s):+d}%{b}|{b}{movement(s):.0f}%{b}|{s.ev}|{total}'\n",
|
||||
" b = '**' * is_swing(s)\n",
|
||||
" yield (f'|{swing_name(s)}|{b}{net(s):+d}%{b}|{b}{movement(s):.0f}%{b}|{s.ev}|{total}'\n",
|
||||
" f'|{s.approvals[d]}%|{s.disapprovals[d]}%|{undecided(s, now)}%|{𝝈(s):3.1f}%|')\n",
|
||||
" \n",
|
||||
"def swing_name(s) -> str: return '**' + s.name.upper() + '**' if is_swing(s) else s.name\n",
|
||||
"\n",
|
||||
"md(by_state(states))"
|
||||
"by_state(states)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Popularity Above Replacement President\n",
|
||||
"# Popularity Above Replacement President (PARP) table\n",
|
||||
"\n",
|
||||
"Fivethirtyeight is a combination sports/politics site, and it has a lot of statistics about sports players and how much better they are than the average replacement player. Given that, they [decided](https://fivethirtyeight.com/features/the-states-where-trump-is-more-and-less-popular-than-he-should-be/) to rate the president's approval versus each state's overall approval of his party (in recent elections), which is a way of rating the president's performance versus an average replacement candidate from the same party. I'll duplicate that work and keep it up to date.\n",
|
||||
"\n",
|
||||
"There are only four states where Trump is exceeding a replacement Republican (i.e., has a positive PARP): one deep-red, deep South state, Mississippi, and three deep-blue coastal states, Rhode Island, Hawaii, and Massachussetts."
|
||||
"There are only four states where Trump is exceeding a replacement Republican (i.e., has a positive PARP): one deep-red southern state, Mississippi, and three deep-blue coastal states, Rhode Island, Hawaii, and Massachussetts. Again, the swing states are **bold CAPITALIZED**."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/markdown": [
|
||||
"|State|PARP|Lean|Net|EV|\n",
|
||||
"|State|PARP|Net|Lean|EV|\n",
|
||||
"|-|-|-|-|-|\n",
|
||||
"|Rhode Island|+6|-26|-20|4|\n",
|
||||
"|Hawaii|+3|-36|-33|4|\n",
|
||||
"|Massachusetts|+2|-29|-27|11|\n",
|
||||
"|Mississippi|+2|+15|+17|6|\n",
|
||||
"|Rhode Island|+6|-20|-26|4|\n",
|
||||
"|Hawaii|+3|-33|-36|4|\n",
|
||||
"|Massachusetts|+2|-27|-29|11|\n",
|
||||
"|Mississippi|+2|+17|+15|6|\n",
|
||||
"|Alabama|+0|+27|+27|9|\n",
|
||||
"|Louisiana|+0|+17|+17|8|\n",
|
||||
"|New York|+0|-22|-22|29|\n",
|
||||
"|Delaware|-1|-14|-15|3|\n",
|
||||
"|California|-4|-24|-28|55|\n",
|
||||
"|Maine|-4|-5|-9|4|\n",
|
||||
"|Florida|-5|+5|+0|29|\n",
|
||||
"|New Jersey|-5|-13|-18|14|\n",
|
||||
"|Virginia|-6|+0|-6|13|\n",
|
||||
"|Illinois|-7|-13|-20|20|\n",
|
||||
"|South Carolina|-7|+17|+10|9|\n",
|
||||
"|Maryland|-8|-23|-31|10|\n",
|
||||
"|New Mexico|-8|-7|-15|5|\n",
|
||||
"|Pennsylvania|-8|+1|-7|20|\n",
|
||||
"|Kentucky|-9|+23|+14|8|\n",
|
||||
"|North Carolina|-9|+5|-4|15|\n",
|
||||
"|Vermont|-10|-24|-34|3|\n",
|
||||
"|Georgia|-11|+12|+1|16|\n",
|
||||
"|Michigan|-11|-1|-12|16|\n",
|
||||
"|Ohio|-11|+7|-4|18|\n",
|
||||
"|Nevada|-12|+1|-11|6|\n",
|
||||
"|Tennessee|-12|+28|+16|11|\n",
|
||||
"|West Virginia|-12|+30|+18|5|\n",
|
||||
"|Colorado|-13|-1|-14|9|\n",
|
||||
"|Connecticut|-13|-11|-24|7|\n",
|
||||
"|Missouri|-13|+19|+6|10|\n",
|
||||
"|Oregon|-13|-9|-22|7|\n",
|
||||
"|Minnesota|-14|-2|-16|10|\n",
|
||||
"|Texas|-14|+17|+3|38|\n",
|
||||
"|Wisconsin|-14|+1|-13|10|\n",
|
||||
"|Alaska|-15|+15|+0|3|\n",
|
||||
"|Arizona|-15|+9|-6|11|\n",
|
||||
"|Idaho|-15|+35|+20|4|\n",
|
||||
"|Indiana|-15|+18|+3|11|\n",
|
||||
"|Montana|-15|+18|+3|3|\n",
|
||||
"|Arkansas|-16|+24|+8|6|\n",
|
||||
"|Iowa|-18|+6|-12|6|\n",
|
||||
"|Washington|-18|-12|-30|12|\n",
|
||||
"|District of Columbia|-19|-43|-62|3|\n",
|
||||
"|New Hampshire|-21|+2|-19|4|\n",
|
||||
"|Kansas|-22|+23|+1|6|\n",
|
||||
"|Nebraska|-22|+24|+2|5|\n",
|
||||
"|Oklahoma|-25|+34|+9|7|\n",
|
||||
"|South Dakota|-25|+31|+6|3|\n",
|
||||
"|Wyoming|-25|+47|+22|3|\n",
|
||||
"|Utah|-29|+31|+2|6|\n",
|
||||
"|North Dakota|-32|+33|+1|3|"
|
||||
"|Delaware|-1|-15|-14|3|\n",
|
||||
"|California|-4|-28|-24|55|\n",
|
||||
"|Maine|-4|-9|-5|4|\n",
|
||||
"|**FLORIDA**|-5|+0|+5|29|\n",
|
||||
"|New Jersey|-5|-18|-13|14|\n",
|
||||
"|Virginia|-6|-6|+0|13|\n",
|
||||
"|Illinois|-7|-20|-13|20|\n",
|
||||
"|South Carolina|-7|+10|+17|9|\n",
|
||||
"|Maryland|-8|-31|-23|10|\n",
|
||||
"|New Mexico|-8|-15|-7|5|\n",
|
||||
"|Pennsylvania|-8|-7|+1|20|\n",
|
||||
"|Kentucky|-9|+14|+23|8|\n",
|
||||
"|**NORTH CAROLINA**|-9|-4|+5|15|\n",
|
||||
"|Vermont|-10|-34|-24|3|\n",
|
||||
"|**GEORGIA**|-11|+1|+12|16|\n",
|
||||
"|Michigan|-11|-12|-1|16|\n",
|
||||
"|**OHIO**|-11|-4|+7|18|\n",
|
||||
"|Nevada|-12|-11|+1|6|\n",
|
||||
"|Tennessee|-12|+16|+28|11|\n",
|
||||
"|West Virginia|-12|+18|+30|5|\n",
|
||||
"|Colorado|-13|-14|-1|9|\n",
|
||||
"|Connecticut|-13|-24|-11|7|\n",
|
||||
"|**MISSOURI**|-13|+6|+19|10|\n",
|
||||
"|Oregon|-13|-22|-9|7|\n",
|
||||
"|Minnesota|-14|-16|-2|10|\n",
|
||||
"|**TEXAS**|-14|+3|+17|38|\n",
|
||||
"|Wisconsin|-14|-13|+1|10|\n",
|
||||
"|**ALASKA**|-15|+0|+15|3|\n",
|
||||
"|**ARIZONA**|-15|-6|+9|11|\n",
|
||||
"|Idaho|-15|+20|+35|4|\n",
|
||||
"|**INDIANA**|-15|+3|+18|11|\n",
|
||||
"|**MONTANA**|-15|+3|+18|3|\n",
|
||||
"|Arkansas|-16|+8|+24|6|\n",
|
||||
"|Iowa|-18|-12|+6|6|\n",
|
||||
"|Washington|-18|-30|-12|12|\n",
|
||||
"|District of Columbia|-19|-62|-43|3|\n",
|
||||
"|New Hampshire|-21|-19|+2|4|\n",
|
||||
"|**KANSAS**|-22|+1|+23|6|\n",
|
||||
"|**NEBRASKA**|-22|+2|+24|5|\n",
|
||||
"|Oklahoma|-25|+9|+34|7|\n",
|
||||
"|**SOUTH DAKOTA**|-25|+6|+31|3|\n",
|
||||
"|Wyoming|-25|+22|+47|3|\n",
|
||||
"|**UTAH**|-29|+2|+31|6|\n",
|
||||
"|**NORTH DAKOTA**|-32|+1|+33|3|"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Markdown object>"
|
||||
@@ -572,14 +606,15 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def parp(state): return net(state) - state.lean \n",
|
||||
"def parp(state) -> int: return net(state) - state.lean \n",
|
||||
"\n",
|
||||
"@markdown\n",
|
||||
"def by_parp(states, d=now):\n",
|
||||
" yield header('|State|PARP|Lean|Net|EV|')\n",
|
||||
" yield header('|State|PARP|Net|Lean|EV|')\n",
|
||||
" for s in sorted(states, key=parp, reverse=True):\n",
|
||||
" yield (f'|{s.name}|{parp(s):+d}|{s.lean:+d}|{net(s):+d}|{s.ev}|')\n",
|
||||
" yield (f'|{swing_name(s)}|{parp(s):+d}|{net(s):+d}|{s.lean:+d}|{s.ev}|')\n",
|
||||
"\n",
|
||||
"md(by_parp(states))"
|
||||
"by_parp(states)"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
+1283
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user