Final Post: 2024 Presidential Forecast

Alex Heuss

2024/11/03

Introductory Note

Over the course of nine weeks, we’ve explored the power of the economy, incumbency, polling, demographics, and certain campaign data in predicting election outcomes. For the past several weeks, my model has predicted the same outcome: Harris wins Wisconsin, Michigan and Pennsylvania, while Trump takes the rest. My national popular vote prediction has steadily narrowed, with Trump now within a percentage point of Harris. If anything has become clear to me over the course of this process, it is that this race is truly a coin flip. I’m excited to see how my predictions fare.

Model Breakdown

In forecasting the 2024 Presidential Election, I created two separate models, one to forecast the national popular vote and another to predict the electoral college. Both of my forecasts rely primarily on fundamentals, polling and lagged vote share. My models also include measures of “partisan swing,” which measures the change in partisan identification for a party between 2024 and either the year prior or the election prior, and is motivated by an underlying theory of increasing partisanship and polarization in the electorate.

My national popular vote prediction model uses LASSO to select the most influential predictors from a lengthy list of options including: incumbency measures, June presidential approval rating, percent of the country identifying as Democrat, Republican or Independent, and how those numbers changed from both the previous year and the prior election, lagged vote share, weekly polling averages in the 30 weeks leading up to the election, and economic measures of GDP, RDPI and stock prices.

The Lasso regression model minimizes the following loss function:

$$ \underset{\beta}{\text{min}}\quad \sum_{i=1}^{n} \left( y_i - \hat{y}_i \right)^2 + \lambda \sum_{j=1}^{p} |\beta_j| $$

where:

The LASSO coefficients are shown in the following table:

Coefficient
(Intercept)12.164
party0.000
incumbent0.000
incumbent_party0.000
prev_admin0.000
deminc0.000
juneapp0.000
percent0.000
two_party_percent0.000
ind_percent-0.034
year_prior0.000
year_prior_2p0.000
swing10.109
swing1_2p0.000
prior_election0.000
prior_election_2p0.000
swing40.000
swing4_2p0.000
pv_lag10.072
pv_lag20.000
nat_weeks_left_10.275
nat_weeks_left_20.000
nat_weeks_left_30.000
nat_weeks_left_40.000
nat_weeks_left_50.168
nat_weeks_left_60.000
nat_weeks_left_70.000
nat_weeks_left_80.000
nat_weeks_left_90.000
nat_weeks_left_100.000
nat_weeks_left_110.040
nat_weeks_left_120.000
nat_weeks_left_130.000
nat_weeks_left_140.000
nat_weeks_left_150.000
nat_weeks_left_160.000
nat_weeks_left_170.016
nat_weeks_left_180.245
nat_weeks_left_190.000
nat_weeks_left_200.000
nat_weeks_left_210.000
nat_weeks_left_220.000
nat_weeks_left_230.000
nat_weeks_left_240.000
nat_weeks_left_250.000
nat_weeks_left_260.000
nat_weeks_left_270.000
nat_weeks_left_280.000
nat_weeks_left_290.000
nat_weeks_left_300.000
q2_gdp_growth0.000
q2_rdpi_growth0.000
GDP0.000
RDPI0.000
nat_unemployment0.000
stock_adj_close0.000

My LASSO model selected 8 predictors as important in reducing the error of my model: percent of the country identifying as independent, the change in party identification for either party from the year preceding the election, vote share from the previous election, and five different weeks of polling, including the week just prior to the election. The cross-validated R-squared value for my model is 0.88. Polling data and partisan swing have the largest coefficient sizes. An example interpretation of one of the coefficients would be: for each increase of one percentage point in a party’s identification from the year prior to the election to election year, that party’s candidate’s vote share increases by 0.1 percentage points. On the surface, that may not seem like a lot, but several “small” coefficient predictors add up.

Electoral College Vote

My electoral college model takes in less predictive variables. I make two separate models for predicting the electoral college, one for states with significant polling aggregate data on FiveThirtyEight, and one for those without. Predictive variables for both models include: state-level lagged vote share for the two prior elections, whether the candidate is a member of the incumbent party, national quarter 2 GDP growth, average state-level unemployment, the change in partisan identification for either party from the last election, and state fixed effects. For states with polling aggregates, the mean polling average and latest polling average are included in my model. My linear model uses the following equation:

$$ y_{ij} = \beta_0 + \beta_1 \text{voteshare}_{ij-1} + \beta_2 \text{voteshare}_{ij-2} + \beta_3 \text{incumbentparty}_{j} + \beta_4 \text{Q2GDP}_{j} + \beta_5 \text{unemployment}_{ij} + \beta_6 \text{partyswing}_{j} + \alpha_{i} + \epsilon_{ij} $$

Where \(i\) denotes the state and \(j\) the year.

## 
## Call:
## lm(formula = .outcome ~ ., data = dat)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.6864 -0.9452  0.0075  1.0198  6.2622 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             8.490611   1.639295   5.179 6.01e-07 ***
## latest_pollav_DEM       0.636025   0.050577  12.575  < 2e-16 ***
## mean_pollav_DEM         0.063184   0.044010   1.436 0.152856    
## D_pv_lag1               0.172542   0.033103   5.212 5.16e-07 ***
## D_pv_lag2              -0.037803   0.025319  -1.493 0.137202    
## incumbent_partyTRUE     0.249170   0.345263   0.722 0.471443    
## q2_gdp_growth           0.022438   0.015765   1.423 0.156407    
## avg_state_unemployment  0.107177   0.098937   1.083 0.280153    
## dem_perc_swing         -0.006054   0.013972  -0.433 0.665316    
## rep_perc_swing         -0.006430   0.015751  -0.408 0.683592    
## stateCalifornia         2.116318   1.055291   2.005 0.046440 *  
## stateColorado           0.350983   0.995406   0.353 0.724806    
## stateFlorida           -0.916874   1.002994  -0.914 0.361888    
## stateGeorgia           -0.183100   1.015898  -0.180 0.857175    
## stateMaine              0.015522   1.391019   0.011 0.991109    
## stateMaryland           2.896403   1.092723   2.651 0.008763 ** 
## stateMassachusetts      3.919226   1.091799   3.590 0.000429 ***
## stateMichigan           1.912411   1.052550   1.817 0.070919 .  
## stateMinnesota          1.204050   1.037450   1.161 0.247373    
## stateMissouri          -0.536897   1.035603  -0.518 0.604800    
## stateMontana           -2.704191   1.609727  -1.680 0.094740 .  
## stateNebraska          -3.878691   1.212902  -3.198 0.001640 ** 
## stateNevada             0.136722   1.312436   0.104 0.917149    
## `stateNew Hampshire`    0.192059   1.092616   0.176 0.860668    
## `stateNew Mexico`       1.043815   1.297480   0.804 0.422191    
## `stateNew York`         1.510022   1.064815   1.418 0.157918    
## `stateNorth Carolina`  -1.280866   1.035287  -1.237 0.217649    
## stateOhio              -0.673344   1.007398  -0.668 0.504749    
## statePennsylvania       1.157246   1.023277   1.131 0.259618    
## stateTexas             -0.757347   0.992960  -0.763 0.446647    
## stateVirginia           0.854729   0.999525   0.855 0.393632    
## stateWashington         1.519807   1.024802   1.483 0.139846    
## stateWisconsin          1.406889   1.020135   1.379 0.169598    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.914 on 177 degrees of freedom
## Multiple R-squared:  0.936,	Adjusted R-squared:  0.9244 
## F-statistic: 80.86 on 32 and 177 DF,  p-value: < 2.2e-16

## 
## Call:
## lm(formula = .outcome ~ ., data = dat)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -8.826 -2.525  0.079  2.566  9.982 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            13.584297   4.080296   3.329  0.00114 ** 
## D_pv_lag1               0.571003   0.070990   8.043  5.1e-13 ***
## D_pv_lag2               0.097555   0.064725   1.507  0.13422    
## incumbent_partyTRUE    -2.563009   0.957730  -2.676  0.00842 ** 
## q2_gdp_growth          -0.027435   0.038468  -0.713  0.47703    
## avg_state_unemployment -0.030232   0.270109  -0.112  0.91106    
## dem_perc_swing          0.004528   0.027651   0.164  0.87019    
## rep_perc_swing         -0.037591   0.031593  -1.190  0.23631    
## stateAlaska             1.341766   3.674850   0.365  0.71562    
## stateArkansas           1.928218   2.240047   0.861  0.39096    
## stateConnecticut        5.612684   2.199396   2.552  0.01189 *  
## stateDelaware           5.855018   4.019572   1.457  0.14767    
## stateHawaii             5.296471   4.428031   1.196  0.23386    
## stateIdaho             -2.990001   3.829487  -0.781  0.43637    
## stateIllinois           5.937094   2.197593   2.702  0.00784 ** 
## stateIndiana            1.359286   2.087961   0.651  0.51621    
## stateIowa               2.425217   2.302244   1.053  0.29414    
## stateKansas             0.558267   2.284349   0.244  0.80732    
## stateKentucky          -1.752716   3.708228  -0.473  0.63726    
## stateLouisiana          1.805360   2.217026   0.814  0.41698    
## stateMississippi        1.623151   2.956515   0.549  0.58396    
## `stateNew Jersey`       5.239889   2.139260   2.449  0.01566 *  
## `stateNorth Dakota`    -4.363556   3.252359  -1.342  0.18208    
## stateOklahoma          -1.981762   2.699730  -0.734  0.46426    
## stateOregon             4.564242   2.104922   2.168  0.03198 *  
## `stateRhode Island`     6.972337   3.552869   1.962  0.05188 .  
## `stateSouth Carolina`   2.140027   2.634950   0.812  0.41820    
## `stateSouth Dakota`    -3.826466   3.372609  -1.135  0.25868    
## stateTennessee          1.360200   2.093539   0.650  0.51704    
## stateUtah              -2.104533   3.056566  -0.689  0.49237    
## stateVermont            6.587487   4.348919   1.515  0.13230    
## `stateWest Virginia`    0.815409   2.297063   0.355  0.72319    
## stateWyoming           -1.648196   2.570163  -0.641  0.52249    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.716 on 128 degrees of freedom
## Multiple R-squared:  0.7859,	Adjusted R-squared:  0.7324 
## F-statistic: 14.68 on 32 and 128 DF,  p-value: < 2.2e-16

For my model with polls, the latest poll average holds significant predictive weight, as does a state’s most recent presidential election vote share. On the other hand, lagged vote share is the most important for state’s without polls, followed by incumbency. We see also in both models that state fixed effects can have very large coefficients and thus may have large predictive power, despite being less significant than other variables. My models with polls has a 0.91 cross-validated r-squared, however my model without polls only has an r-squared of 0.66. Luckily, the states without polls are not close in this election, so the precise vote share prediction is not as important as in swing states.

Predictions

CandidatePredicted Vote ShareLower BoundUpper Bound
Harris49.0219846.9067251.13725
Trump48.0850446.5711449.59895

Electoral College

All in all, my model predicts that Harris will win the electoral college, 270-268 - an insanely tight margin.

WinnerStates WonElectors
Democrat23270
Republican28268

The following graph presents the breakdown for my swing state predictions including confidence intervals.

StateHarris PredictionLowerUpperMarginWinner
Michigan51.197247.445854.94872.3945Democrat
Pennsylvania50.161446.410053.91280.3228Democrat
Wisconsin50.571246.819854.32261.1424Democrat
Arizona48.333544.582152.0850-3.3329Republican
Georgia48.311044.559652.0624-3.3780Republican
Nevada48.996545.245152.7479-2.0070Republican
North Carolina47.031943.280550.7833-5.9362Republican

In a race as tight as 2024, it is nearly impossible to predict tight swing states and have a confidence interval that puts one candidate as a clear winner, and my predictions are no exception.

Below is the map of all my electoral college predictions and their associated vote share margins. Negative vote shares represent Trump wins and positive values represent Harris wins.