Quelle est l'efficacité du vaccin ?

Ce que les données de la DREES révèle de l'efficaité des vaccins

Soit $M$ : l’évènement malade du Covid (aussi bien contaminé, hospitalisé, réanimation, décès).

Soit $V$: l’évènement vacciné contre le Covid.

Alors on note $P_{\overline{V}}(M)$ la probabilité d’attraper le covid sans vaccin. Un vaccin avec une efficacité $E$ (ex. 95%) signifie que la probabilité $P_V(M)$ d’attraper la maladie vacciné est réduit de 95% par rapport à $P_{\overline{V}}(M)$, comme expliqué ici. Ce qui se traduit par

\begin{array}{rcl} \frac{P_{\overline{V}}(M)-P_V(M)}{P_{\overline{V}}(M)} & = & E
P_V(M) & = & (1-E)*P_{\overline{V}}(M) \end{array}

Si une population a $C_v$ % de couverture vaccinale, uniformément répartis dans la société. Alors, on peut noter la probabilité qu’un personne soit vaccinées $P(V) = C_v$, ainsi que $P(\overline{V}) = 1 - C_v$.

Donc si nous voulons $R$ le ratio de gens vaccinés parmis les gens malades:

\[\begin{array}{rcl} R & = & \frac{Nb\ personnes\ vaccinées\ et\ malades}{Nb\ personnes\ malades} \\ R & = & \frac{P(V \cap M)}{P(M)} \\ R & = & \frac{P(V \cap M)}{P(V \cap M) + P(\overline{V} \cap M)} \\ R & = & 1 / \left[ 1 + \frac{P(\overline{V} \cap M)}{P(V \cap M)} \right] \\ R & = & 1 / \left[ 1 + \frac{P(\overline{V}) * P_{\overline{V}}(M)}{P(V) * P_V(M)} \right] \\ R & = & 1 / \left[ 1 + \frac{P(\overline{V}) * P_{\overline{V}}(M)}{P(V) * P_{\overline{V}}(M)*(1-E)} \right] \\ R & = & 1 / \left[ 1 + \frac{P(\overline{V})}{(1-E)*P(V)} \right] \\ R(E, C_v) & = & 1 / \left[ 1 + \frac{1 - C_v}{(1-E)*C_v} \right] \\ E(R, C_v) & = & 1 + \frac{1 - 1/C_v}{1/R - 1} \end{array}\]

On peut vérifier le model avec quelques valeurs triviales:

  • $\forall C_v, R(E=0, C_v) = C_v$, si le vaccin n’a aucune efficacité, le ratio des nouveaux malades vaccinés est égal au ratio des citoyens vaccinés
  • $\forall C_v, R(E \to 1, C_v) \to 0$, si la vaccin est 100% efficace, il n’y a aucun nouveau malade vacciné
  • $\forall E, R(E, C_v=1) = 1$, si toute la population est vaccinée, tous les nouveaux malades sont vaccinés
  • $\forall E, R(E, C_v \to 0) \to 0$, si personne n’est vacciné, il n’y a aucun nouveau malade vacciné
import numpy as np
import pandas as pd
import plotly.graph_objects as go
from plotly.offline.offline import plot
def E(R, V):
    return 1 + (1 - 1 / V) / (1 / R - 1)
fig = fig = go.Figure()
ratio = np.linspace(0.01, 99.99, 10000)

for vacc in range(5, 100, 5):
    eff = E(ratio / 100, vacc / 100)
    eff[eff < 0] = None
    fig.add_trace(go.Scatter(name=f"R(Cv={vacc} %)", x=ratio, y=eff))

fig.update_layout(title="Par de l'efficacité du vaccin en fonction des vaccinés dans les nouveaux malades",
                 height=800)
fig.update_xaxes(title_text="% des vaccinés malades")
fig.update_yaxes(title_text="Efficacité des vaccins")

#fig.show()
plot(fig, include_plotlyjs=False, include_mathjax=False, output_type='div')
Pays Date Couverture Ratio Source Efficacité réelle Perte d’efficacité
Israel Juillet 2021 85 % 45 % LeMonde 86 % 9 %
France Juin 2021 35 % 7 % Gouv 86 % 9 %
France Décembre 2021 70 % 57 % Libération 43 % 54%
Belgique Novembre 2021 75 % 64 % Lecho.be 40 % 58 %
UK Octobre 2021 68 % 60 % Gouv 35 % 63 %

Analyse données de la DREES

https://data.drees.solidarites-sante.gouv.fr/explore/dataset/covid-19-resultats-issus-des-appariements-entre-si-vic-si-dep-et-vac-si/information/?disjunctive.vac_statut

df = pd.read_csv('covid-19-resultats-issus-des-appariements-entre-si-vic-si-dep-et-vac-si.csv', sep=';')
df["HC"].sum(), df["HC_PCR+"].sum()
(61813.09999999999, 45508.88)
df["date"] = pd.to_datetime(df["date"])
df = df[["date", "vac_statut", "HC_PCR+"]]
df.head()
date vac_statut HC_PCR+
0 2021-05-31 Non-vaccinés 214.46
1 2021-05-31 Primo dose récente 12.94
2 2021-06-01 Non-vaccinés 198.54
3 2021-06-01 Primo dose efficace 20.14
4 2021-06-03 Non-vaccinés 154.75

On ne garde que les hospitalisations complet avec PCR positif

df["vac_statut"].unique()
array(['Non-vaccinés', 'Primo dose récente', 'Primo dose efficace',
       'Complet entre 3 mois et 6 mois - sans rappel',
       'Complet de moins de 3 mois - avec rappel',
       'Complet de moins de 3 mois - sans rappel',
       'Complet entre 3 mois et 6 mois - avec rappel',
       'Complet de 6 mois et plus - sans rappel',
       'Complet de 6 mois et plus - avec rappel'], dtype=object)

pour les vaccinations sans antécédent de Covid-19 avec vaccins non monodose (hors Janssen) :

  • Non vacciné (0) : personne n’ayant jamais reçu d’injection de vaccin contre le Sars-Cov-2
  • Primo dose récente (1-) : personne ayant reçu une première dose depuis 14 jours ou moins
  • Primo dose efficace (1+) : personne ayant reçu une première dose depuis plus de 14 jours ou ayant reçu une deuxième dose depuis 7 jours ou moins
  • Complet (C) : personne ayant reçu une deuxième dose depuis plus de 7 jours
def reduce(statut):
    if statut in ["Non-vaccinés", "Primo dose récente", 'Primo dose efficace']:
        return 'Non-vaccinés'
    else:
        return 'Vaccinés'
df['vac_statut'] = df['vac_statut'].apply(reduce)
data = pd.pivot_table(df, index="date", columns="vac_statut", aggfunc=np.sum)["HC_PCR+"]
data
vac_statut Non-vaccinés Vaccinés
date
2021-05-31 254.56 36.44
2021-06-01 232.51 32.50
2021-06-02 244.06 42.75
2021-06-03 177.71 32.28
2021-06-04 224.67 24.33
... ... ...
2021-12-01 283.76 343.14
2021-12-02 310.36 329.67
2021-12-03 312.07 335.38
2021-12-04 245.66 274.24
2021-12-05 215.33 243.26

189 rows × 2 columns

fig = go.Figure()

for c in data.columns:
        fig.add_trace(go.Bar(name=c, x=data.index, y=data[c]))
fig.update_layout(barmode='stack', title="Indice d'hospitalisations chaque jour")

#fig.show()
plot(fig, include_plotlyjs=False, include_mathjax=False, output_type='div')

L’échelle n’est clairement pas le nombre d’hospitalisations. Durant la 4e vague on était à 10 000 hospitalisations par jour. Cela doit être un taux d’incidence…. D’après les estimations il serait pour 300 000 habitants.

data['R'] = data['Vaccinés'] / data.sum(axis=1) 
fig = go.Figure()

fig.add_trace(go.Scatter(name=c, x=data.index, y=data['R']))
fig.update_layout(title="Ratio des vaccinés en hospitalisation")

#fig.show()
plot(fig, include_plotlyjs=False, include_mathjax=False, output_type='div')

Une dernière étape, la couverture vaccinale

https://www.data.gouv.fr/fr/datasets/donnees-relatives-aux-personnes-vaccinees-contre-la-covid-19-1/

doses = pd.read_csv('vacsi12-fra-2021-12-16-19h06.csv', sep=";")
doses.tail()
fra jour n_dose1 n_complet n_rappel n_cum_dose1 n_cum_complet n_cum_rappel couv_dose1 couv_complet couv_rappel
349 FR 2021-12-11 19439 30747 477303 52292401 51193618 14329978 90.7 88.8 24.8
350 FR 2021-12-12 5417 7172 158089 52297818 51200790 14488067 90.7 88.8 25.1
351 FR 2021-12-13 19945 30888 640845 52317763 51231678 15128912 90.7 88.8 26.2
352 FR 2021-12-14 25762 35884 834079 52343525 51267562 15962991 90.8 88.9 27.7
353 FR 2021-12-15 26016 39710 750264 52369541 51307272 16713255 90.8 89.0 29.0
doses.index = pd.to_datetime(doses["jour"])
couv = doses["n_complet"].cumsum() / 67400000
rappel = doses["n_rappel"].cumsum() / 67400000
fig = go.Figure()

fig.add_trace(go.Scatter(name="% rappel", x=rappel.index, y=rappel))
fig.add_trace(go.Scatter(name="% couverture", x=couv.index, y=couv))

fig.update_layout(title="Couverture complete")

#fig.show()
plot(fig, include_plotlyjs=False, include_mathjax=False, output_type='div')

On peut regrouper les deux

eff = E(data['R'], couv)
fig = go.Figure() 

fig.add_trace(go.Scatter(name="% rappel", x=rappel.index, y=rappel))
fig.add_trace(go.Scatter(name="% couverture", x=couv.index, y=couv))
fig.add_trace(go.Scatter(name="% efficacité vaccin", x=eff.index, y=eff.rolling(window=10).mean()))
fig.add_trace(go.Scatter(name="% vacc hosp", x=data.index, y=data['R'].rolling(window=10).mean()))
fig.update_layout(title="Situation en France")

#fig.show()
plot(fig, include_plotlyjs=False, include_mathjax=False, output_type='div')