Who will win the 2027 French presidential election?
Bayesian poll-aggregation forecast. This is work in progress, I would love your feedback.
Choose among the following. On the left, you can choose to include the Green Party candidate or not, and you can choose one of the three Socialist candidates. At the center, you must select either Attal or Philippe. For Les Républicains, pick one or none. Only candidates polled recently enough to estimate are shown. All the "fixed" major and minor candidates (including Le Pen since she confirmed she was running) are always included. The forecast recomputes simulated results from the posterior draws.
How to read this forecast
- All panels are interactive: hover over the plots to read more information.
- This model uses polls to simulate the upcoming French presidential election 1,000 times.
- The panel Who wins the presidency? reports the share of simulations won by each candidate.
- The panel First-round vote intention over time shows the polls used in the model, which tell us where candidates appear to stand today.
- The panel First-round in 1,000 simulated elections displays the first-round scores in 1,000 simulations.
- The last panel, Most likely runoff match-ups, shows the simulated runoff results in the most frequent pairings coming out of the simulated first rounds.
- Note 1: past French elections tell me how uncertain the estimates should become between now and election day.
- Note 2 candidate withdrawals are scenarios, not just predictions. They layer an explicit assumption about where a departing candidate's voters go on top of the poll-driven forecast.
Who wins the presidency?
Each dot is one simulated election, placed in the row of the candidate who won it — so the width of each cloud is that candidate's chance of winning. Hover a dot to see that simulation's first-round result and the runoff it produced. ()
First-round vote intention over time
Lines are the model's estimate; shaded bands are the 80% credible interval, widening toward election day. Dots are individual polls, each shown at the candidate's reported share (including alternatives not in the selected line-up).
First round in 1,000 simulated elections
Each dot is one simulated first-round result. The two candidates with the highest scores advance to the runoff, so candidates clustered near the top are fighting for the second qualifying spot.
Most likely runoff match-ups
The runoffs that occur most often across simulations. Each dot is one simulated runoff, placed by the RN candidate's second-round share and coloured by the winner; the dashed line is the 50% threshold. Hover a dot for that runoff's result.
When you untick a candidate, they “drop out” and their vote is redistributed to the remaining candidates by inverse-distance weighting on a left–right axis (nearer candidates receive more), with a proportion of abstention for voters who would rather stay home than vote for anyone but their favorite candidate. These positions and knobs are explicit assumptions below: adjust them and everything is recomputed.
Candidate positions (0 = far left → 100 = far right)
The left-right ordering is fixed: each slider is stuck between its neighbours. You therefore calibrate distances, not who sits to the left of whom.
The forecast is a Bayesian poll-aggregation model in the tradition of Nate Silver's FiveThirtyEight and the Economist's 2020 model (Gelman, Morris & Heidemanns), which in turn build on Linzer (2013). I wanted to adapt these to France's two-round system. In this system, many candidates enter the first round and then, either (i) one candidate receives an absolute majority of the votes and is elected, or (ii) the two candidates who receive the highest number of votes in the first round advance to the runoff, which takes place two weeks later. My model has two stages: a first-round vote-share model and a runoff model. It is a Bayesian model, which requires setting priors. Some are deliberate regularisation choices (e.g. the fixed random-walk step and the runoff-strength prior); the key forecast-uncertainty parameters — how fast uncertainty grows toward election day, and the irreducible election-day poll error — are calibrated on the 2012, 2017, and 2022 elections. Three cycles is not a lot of history, so these are estimated with real uncertainty. Everything is fit in Stan. This page recomputes the forecast for the candidate line-up you select from the posterior draws.
This is work in progress and I appreciate your feedback. Credits (but no responsibility for my errors) are due to Ronald Neath, who taught the Bayesian Statistics course I took in the Fall of 2023. I used LLMs to think through part of the modeling, and for a lot of the dynamic visualization (I have no prior D3.js expertise). The data comes from Wikipedia.
1 · First round: latent support and random walk
Consider candidates c = 1,…,C over weeks w = 1,…,W (where W is the election week). βc,w is the latent support of candidate c in week w, on an unbounded scale.
The latent support of each candidate "wanders" randomly from week to week. This is the "random walk" from Linzer (2013) commonly found in other forecasts. Each week, the random walk adds a value randomly drawn from a Normal distribution to the previous week's latent support of each candidate. Here the weekly step σ is fixed (this is a smoothing choice, it's not estimated from the data): it controls how much the latent line may move between polls while I estimate where the candidates stand today. This in-sample walk is distinct from the forecast-horizon uncertainty (how far opinion can still drift from the last poll to election day), which is governed by a separate, historically-calibrated random walk described in Section 3, and is what actually makes the bands widen into the future.
So the latent support of candidate c in week w is:
With priors εc,w ∼ Normal(0, 1) and βc,1 ∼ Normal(0, 1.52).
The overall level of the latent supports is not identified by the softmax, as adding the same constant to every βc,w would leave all shares unchanged. Each week is therefore softly anchored with a sum-to-zero constraint: ∑c βc,w ∼ Normal(0, 0.12).
2 · Estimation of the latent support
French polls test different line-ups: one poll may or may not include a given candidate. A poll i fielded in week wi by pollster pi reports shares only over the candidate subset Si present in that hypothesis. I model it as the softmax over that subset Si of the latent supports, plus a pollster effect δp,c.
For each candidate c in poll i in week w, I call ηi,c the sum of the latent support and the pollster effect.
Softmax turns the latent ηi,c into shares θi,c:
Each poll is then a draw from a Multinomial distribution with ñi effective respondents and the vector of probabilities θi for candidates c∈Si:
Because I condition each poll on their restricted line-up, all polls provide conditional shares used to inform the same β. The sample sizes are deflated to an "effective" size ñi reflecting "design effects" and the fact that pollsters test multiple line-ups in the same polls:
3 · Calibration from history, and the forecast
By comparing polls to actual electoral results in the 2012, 2017, and 2022 presidential elections, I estimate how the (squared) error of polls grows with horizon h (time to the election). I use this to calibrate: (i) the parameter of a random walk making variance grow over time, and (ii) an "election-day miss":
where a is the election-day miss and √c the daily step of the random walk. I fit this per cycle, weighting each election equally. The three cycles genuinely disagree, with election-day misses of roughly 1, 3 and 5 points respectively. Rather than picking one, I treat 2027 as new: every simulation draws (a, √c) from a heavy-tailed predictive across the three cycles (central election-day error ≈ 3 points, drift ≈ 0.2 pt/day). This helps propagate the uncertainty from estimating the election-day miss using three elections only.
For the forecast, I take the estimate of the latent state at the last poll week w∗ and add (i) the random-walk drift to election day and (ii) the systematic election-day miss. That component does not shrink with more polls or as election day gets closer.
These elements of horizon spread are added to the latent support of the candidate β̃c, before it is transformed into shares using the softmax function.
ζc, υc ∼ Normal(0,1).
The share for a chosen line-up 𝒜 is the softmax over just those candidates, πc = softmax𝒜(β̃c). The drift and election-day miss standard deviations are the historical quantities discussed above, but mapped from the "shares" scale to the "latent" scale by κ = 1⁄[π(1−π)] ≈ 5.9 (evaluated at a typical π ≈ 0.22), i.e. srw = √c · √7 · κ and serr = a · κ.
4 · Runoff: Bradley–Terry model
I use a paired-comparison model (Bradley & Terry, 1952) that gives every candidate a “strength”, and in which the chance that A beats B depends on the difference in strengths. The model pools head-to-heads and predicts unpolled pairings by transitivity: if A beats C handily and B only narrowly, we can estimate A vs. B. For each candidate's latent runoff strength sc, a head-to-head poll of A vs. B gives A's expected share as
kA ∼ BetaBinomial(ñ, pφ, (1−p)φ),
with sc ∼ Normal(0, 1.52) (with a soft sum-to-zero) and over-dispersion φ ∼ Gamma(2, 0.05).
Bradley–Terry pools sparse matchup polls and predicts any pairing through shared opponents. For a runoff between the first-round top two X, Y, I draw each strength from its full posterior and add a horizon inflation σ2 = √(serr2 + srw,day2 H) to get X's second-round share. This is a single Normal shock on the strength difference sX − sY — not two independent per-candidate shocks, which would widen the gap by a further √2.
ξ ∼ Normal(0,1),
X wins ⇔ pX > ½.
X wins the runoff if that share is larger than 0.5.
Because each candidate has a single runoff strength, a poll of Philippe vs. Bardella sharpens sPhilippe, which in turn tightens the predicted Philippe vs. Le Pen result. Information works through the fact that Le Pen and Bardella have a shared opponent. This is the Bradley–Terry transitivity. This is different from the first round, in which Le Pen and Bardella have separate latent support with no party-level pooling. They are comparable only because they face the same opponents.
5 · What the dots are
Each dot in the plots represents one simulated election. For each election, the simulation draws β̃, s, a latent support and runoff strength for each candidate, from the corresponding posterior distributions. After adding the random walk drift, the election-day miss, and the runoff noise, it then calculates the first-round shares π, takes the top two, calculates their runoff share pX and awards the win to the candidate that clears 0.5. (No first-round candidate comes anywhere near an outright majority, so the simulator always proceeds to a runoff. The direct first-round win mentioned at the top is not separately implemented.) Repeating over the posterior generates the posterior predictive distributions displayed. The trajectory bands are week-by-week quantiles of π, and each dot in the "who wins" and "1,000 simulations" plots is one such draw.
6 · Assumptions and limitations
- Shares are only estimated among expressed votes. Turnout and indecision are not included in the model. The reported shares are renormalised over modelled candidates: undecideds are assumed to split like decideds.
- The line-up is a scenario. I don't make any prediction about primary results and the final line-up.
- Softmax independence. Two candidates never polled together are placed on a common scale only through shared opponents. For true substitutes (e.g., the two RN leaders, or Attal/Philippe for the centre), the softmax would overstate their combined support. This is why I don't allow both to be included in the picker.
- Independent election-day miss. The election-day miss is applied to each candidate independently in latent space, before the softmax. It is not added as a correlated national factor. When I check against history, I find that at the current horizon the model's candidate-gap errors are slightly narrower than in the 2012, 2017, and 2022 record.
- Runoff reuses first-round error calibration. The runoff horizon shock σ2 reuses the election-day miss and drift calibrated from first-round history. Applying them to the two-candidate runoff logit is an additional assumption, not something Bradley–Terry implies.
- Calibration over only three elections. The forecast-uncertainty parameters rest on just three elections, I try to propagate their uncertainty but three elections provide a thin historical basis.
- Polls-only. I use no economic fundamentals, incumbency, approval ratings, or other political variables.
Calibrated quantities
| quantity | symbol | value |
|---|---|---|
| election-day poll error (standard deviation) | a | ≈ 3 pts (central; drawn per sim) |
| opinion drift (random walk) | √c | 0.19 pt/day |
| pollster house-effect sd | σhouse | 0.0107 pt |
| design effect | deff | 2.0 |
| weekly RW step (fixed, smoothing) | σ | 0.045 (latent) |
| share→latent conversion | κ | ≈ 5.9 |