🇫🇷

France 2022 Presidential Election Polls

Published on
November 12, 2021
Updated on
April 28, 2022
‣
📖  Table of content

Candidates

The table below shows the 12 candidates to the French 2022 Presidential Election. Column Polls was their latest 7-day rolling average score before Election Day for the 1st round. Spectrum gives an indication of where the party is on the political spectrum, from far-left to far-right.

Candidate
1st round last polls
1st round result
Political party
Spectrum
Emmanuel MACRON
26.5%
27.85%
The Republic On The Move
···•···
Marine LE PEN
22.4%
23.15%
National Rally
·····•·
Jean-Luc MÉLENCHON
16.5%
21.95%
France Unbowed
·•·····
Éric ZEMMOUR
9.4%
7.07%
Reconquest
······•
Valérie PÉCRESSE
9.0%
4.78%
The Republicans
····•··
Yannick JADOT
5.2%
4.63%
Europe Ecology The Greens
·•·····
Jean LASSALLE
2.9%
3.13%
Resist
···•···
Fabien ROUSSEL
2.5%
2.28%
French Communist Party
·•·····
Nicolas DUPONT-AIGNAN
2.0%
2.06%
Stand Up France
·····•·
Anne HIDALGO
2.1%
1.75%
Socialist Party
··•····
Philippe POUTOU
1.0%
0.77%
New Anticapitalist Party
•······
Nathalie ARTHAUD
0.5%
0.56%
Workers Struggle
•······

Polls for Second Round

Emmanuel Macron and Marine Le Pen have been qualified for the second round of the presidential election on 24th April 2022. The plots show their moving averages over 3 days, with a 95% confidence interval.

super-embed:
<iframe src="https://storage.googleapis.com/charlse/charlse/tour2.html" height="520"><iframe>
‣
Plotly code
# Plotly graph for Macron vs Le Pen

### Format plot
fig = go.Figure(
    layout=go.Layout(
        template='simple_white',
        height=500, width=740, 
        margin=dict(l=15, r=25, b=15,t=40),
        xaxis_range=['2022-01-01', '2022-04-24'], 
        yaxis_range=[0.3, 0.7], 
        yaxis_tickformat='.0%', 
        yaxis_tickfont=dict(size=11, family='Arial'),
        xaxis_tickfont=dict(size=11, family='Arial'),
        legend=dict(yanchor='top', y=1, xanchor='left', x=0, orientation='h'),
        hovermode='x unified',
    )
)

### Plot line
fig.add_trace(go.Scatter(
    x=df_mean_tour2.loc[lambda x: x['candidat'] == 'Macron', 'date'], 
    y=df_mean_tour2.loc[lambda x: x['candidat'] == 'Macron', 'rol_avg'],
    hovertemplate='<extra>{}</extra>%{}'.format('Macron', '{y:.1%}'), 
    mode='lines',
    line_color=candidates_colors['Macron'],
    name='Macron')
)
fig.add_trace(go.Scatter(
    x=df_mean_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'date'], 
    y=df_mean_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'rol_avg'],
    hovertemplate='<extra>{}</extra>%{}'.format('Le Pen', '{y:.1%}'), 
    mode='lines',
    line_color=candidates_colors['Le Pen'],
    name='Le Pen') 
)

### Confidence intervals
fig.add_trace(go.Scatter(
    x=df_mean_tour2.loc[lambda x: x['candidat'] == 'Macron', 'date'], 
    y=df_mean_tour2.loc[lambda x: x['candidat'] == 'Macron', 'rol_ci_low'],
    hoverinfo='skip', showlegend=False,
    mode='lines',
    line=dict(color=candidates_colors['Macron'], width=0)),
)
fig.add_trace(go.Scatter(
    x=df_mean_tour2.loc[lambda x: x['candidat'] == 'Macron', 'date'], 
    y=df_mean_tour2.loc[lambda x: x['candidat'] == 'Macron', 'rol_ci_hi'],
    hoverinfo='skip', showlegend=False,
    mode='lines',
    fill='tonexty',
    line=dict(color=candidates_colors['Macron'], width=0)),
)
fig.add_trace(go.Scatter(
    x=df_mean_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'date'], 
    y=df_mean_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'rol_ci_low'],
    hoverinfo='skip', showlegend=False,
    mode='lines',
    line=dict(color=candidates_colors['Le Pen'], width=0)),
)
fig.add_trace(go.Scatter(
    x=df_mean_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'date'], 
    y=df_mean_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'rol_ci_hi'],
    hoverinfo='skip', showlegend=False,
    mode='lines',
    fill='tonexty',
    opacity=.1, 
    line=dict(color=candidates_colors['Le Pen'], width=0)),
)

### Plot scatter
fig.add_trace(go.Scatter(
    x=df_tour2.loc[lambda x: x['candidat'] == 'Macron', 'date'], 
    y=df_tour2.loc[lambda x: x['candidat'] == 'Macron', 'value'],
    hoverinfo='skip', showlegend=False,
    mode='markers', opacity=.3,
    line_color=candidates_colors['Macron']), 
)
fig.add_trace(go.Scatter(
    x=df_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'date'], 
    y=df_tour2.loc[lambda x: x['candidat'] == 'Le Pen', 'value'],
    hoverinfo='skip', showlegend=False,
    mode='markers', opacity=.3,
    line_color=candidates_colors['Le Pen']), 
)

### Horizontal dotted line at 50%
fig.add_shape(
    type='line',
    y0=.5, y1=.5,
    x0='2022-01-01', x1='2022-04-24',
    line=dict(color='black', width=1, dash='dot')
)

## Display result
fig.show()

Polls for First Round

The graph below aggregates opinion polls for the first round of the election on 10th April 2022, released by the main french polling organizations. Each dot represents a poll result for a candidate, and dots radius is proportional to polls sample size.

super-embed:
<iframe src="https://storage.googleapis.com/charlse/charlse/tour1.html"height="520"><iframe>
‣
Plotly code
# Plotly graph

## Candidates to display
candidates_colors = {
    'Barnier': 'royalblue',
    'Bertrand': 'deepskyblue',
    'Hidalgo': 'lightcoral',
    'Jadot': 'green',
    'Le Pen': 'saddlebrown',
    'Macron': 'orange',
    'Mélenchon': 'firebrick',
    'Pécresse': 'steelblue',
    'Roussel': 'palevioletred',
    'Zemmour': 'black'
}

selected_candidates = sorted(['Macron', 'Le Pen', 'Pécresse',
    'Jadot', 'Zemmour', 'Hidalgo', 'Mélenchon', 'Roussel'])

## Line plot
fig1 = px.line(
    df_mean.loc[lambda x: x['candidat'].isin(selected_candidates)],
    x='date', y='rol_avg', color='candidat', 
    color_discrete_map=candidates_colors
)
fig1.update_traces(hovertemplate='%{y:.1%}', line=dict(width=2.5), showlegend=True)

## Scatter graph
fig2 = px.scatter(
    df_polls.loc[lambda x: x['candidat'].isin(selected_candidates)],
    x='date', y='value', color='candidat', opacity=.2,
    size='norm_sample', size_max=12,
    color_discrete_map=candidates_colors
)
fig2.update_traces(hovertemplate=None, hoverinfo='skip', showlegend=False)

## Display both plots
fig3 = go.Figure(
    data=fig2.data + fig1.data,
    layout=go.Layout(
        template='simple_white',
        height=500, width=740, 
        margin=dict(l=5, r=5, b=5,t=5),
        xaxis_range=['2021-08-15', '2022-04-10'], 
        yaxis_range=[0., .40], 
        yaxis_tickformat='.0%', 
        yaxis_tickfont=dict(size=11, family='Arial'),
        xaxis_tickfont=dict(size=11, family='Arial'),
        legend=dict(yanchor='top', y=1, xanchor='left', x=0, orientation='h')
    )
)
fig3.show()

Sources