Partie 3 Analyse de la relation COVID-19 – Bonheur

Author

NGUYEN Duc Hoang Viet

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

Cette partie analyse la relation entre la pandémie de COVID-19 et les indicateurs de bonheur afin d’identifier d’éventuelles corrélations entre la situation sanitaire et le bien-être des populations.

1 Corrélations entre les indicateurs de bonheur

Cette partie analyse la relation entre la pandémie de COVID-19 et les indicateurs de bonheur en utilisant deux perspectives :

l’exposition globale au COVID-19 (cas totaux) l’intensité des vagues épidémiques (pic d’infection)

1.1 Analyse Analyse Total Cases

1.1.1 Chargement des données

merged_data = pd.read_csv("data/merged_data.csv",index_col=0)
merged_data.shape
merged_data.head()
Regional indicator Ladder score Logged GDP per capita Social support Healthy life expectancy Freedom to make life choices Generosity Perceptions of corruption Ladder score in Dystopia Explained by: Log GDP per capita ... 3/1/23 3/2/23 3/3/23 3/4/23 3/5/23 3/6/23 3/7/23 3/8/23 3/9/23 Total Cases
Country name
Finland Western Europe 7.842 10.775 0.954 72.0 0.949 -0.098 0.186 2.43 1.446 ... 1462169 1462976 1462976 1462976 1462976 1462976 1462976 1462976 1463644 1463644
Denmark Western Europe 7.620 10.933 0.954 72.7 0.946 0.030 0.179 2.43 1.502 ... 3450101 3450223 3450336 3450336 3450336 3450587 3450757 3450897 3451036 3451036
Switzerland Western Europe 7.571 11.117 0.942 74.4 0.919 0.025 0.292 2.43 1.566 ... 4412439 4412439 4412439 4412439 4412439 4412439 4413911 4413911 4413911 4413911
Iceland Western Europe 7.554 10.878 0.983 73.0 0.955 0.160 0.673 2.43 1.482 ... 209093 209093 209093 209093 209093 209093 209137 209137 209137 209137
Netherlands Western Europe 7.464 10.932 0.942 72.4 0.913 0.175 0.338 2.43 1.501 ... 8709011 8709011 8710897 8710897 8710897 8710897 8712835 8712835 8712835 8712835

5 rows × 1161 columns

1.1.2 Top pays les plus touchés

merged_data["Total Cases"].sort_values(ascending=False).head(10)
Country name
US                103802702
India              44690738
France             39866718
Germany            38249060
Brazil             37076053
Japan              33320438
Korea, South       30615522
Italy              25603510
United Kingdom     24658705
Russia             22075858
Name: Total Cases, dtype: int64

1.1.3 Transformation logarithmique

merged_data["log_cases"] = np.log1p(merged_data["Total Cases"])

Cette transformation permet de réduire l’impact des valeurs extrêmes et de stabiliser les analyses statistiques.

1.1.4 Classement des pays

merged_data["cases_rank"] = merged_data["Total Cases"].rank(ascending=False)
merged_data.sort_values("cases_rank").head()
Regional indicator Ladder score Logged GDP per capita Social support Healthy life expectancy Freedom to make life choices Generosity Perceptions of corruption Ladder score in Dystopia Explained by: Log GDP per capita ... 3/3/23 3/4/23 3/5/23 3/6/23 3/7/23 3/8/23 3/9/23 Total Cases log_cases cases_rank
Country name
US North America and ANZ 6.951 11.023 0.920 68.200 0.837 0.098 0.698 2.43 1.533 ... 103648690 103650837 103646975 103655539 103690910 103755771 103802702 103802702 18.458003 1.0
India South Asia 3.819 8.755 0.603 60.633 0.893 0.089 0.774 2.43 0.741 ... 44688722 44689046 44689327 44689593 44689919 44690298 44690738 44690738 17.615277 2.0
France Western Europe 6.690 10.704 0.942 74.000 0.822 -0.147 0.571 2.43 1.421 ... 39839090 39839090 39839090 39847236 39854299 39860410 39866718 39866718 17.501052 3.0
Germany Western Europe 7.155 10.873 0.903 72.500 0.875 0.011 0.460 2.43 1.480 ... 38210850 38210850 38210851 38210851 38231610 38241231 38249060 38249060 17.459630 4.0
Brazil Latin America and Caribbean 6.330 9.577 0.882 66.601 0.804 -0.071 0.756 2.43 1.028 ... 37081209 37081209 37081209 37076053 37076053 37076053 37076053 37076053 17.428482 5.0

5 rows × 1163 columns

1.1.5 Top 10 COVID countries

merged_data = merged_data.reset_index()
merged_data.sort_values("Total Cases", ascending=False)[
         ["Country name", "Total Cases"]
].head(10)
Country name Total Cases
18 US 103802702
134 India 44690738
20 France 39866718
12 Germany 38249060
33 Brazil 37076053
54 Japan 33320438
60 Korea, South 30615522
26 Italy 25603510
16 United Kingdom 24658705
73 Russia 22075858

1.1.6 Relation entre bonheur et COVID-19

merged_data[["Ladder score", "Total Cases"]].corr()
plt.scatter(
    merged_data["Ladder score"],
    merged_data["log_cases"]
)

plt.xlabel("Happiness score")
plt.ylabel("Total COVID cases (log scale)")
plt.title("Happiness vs COVID cases")
plt.show()

Ce nuage de points (scatter plot) met en relation le score de bonheur (axe X) et le nombre total de cas de COVID-19 en échelle logarithmique (axe Y). On observe une tendance positive visible entre les deux variables.

Signification :
De manière contre-intuitive, les pays présentant les scores de bonheur les plus élevés (entre 6 et 8) enregistrent également un nombre total de cas de COVID-19 plus important. Cela s’explique principalement par leur niveau de développement, leur forte connectivité internationale et leur urbanisation élevée. De plus, ces pays disposent de systèmes de santé performants et transparents, permettant un dépistage massif et un enregistrement plus fiable des données, contrairement à de nombreux pays moins développés.

1.2 Analyse Max infection rate

On va observer la relation entre le taux d’infection maximal et les indicateurs de bonheur

1.2.1 Chargement des données

# Calcul des corrélations```{python}
data_merge = pd.read_csv("data/data_merge.csv",index_col=0)
data_merge.head()
Logged GDP per capita Social support Healthy life expectancy Freedom to make life choices Perceptions of corruption
Max infection rate
3243.0 7.695 0.463 52.493 0.382 0.924
4789.0 9.520 0.697 68.999 0.785 0.901
2521.0 9.342 0.802 66.005 0.480 0.752
139853.0 9.962 0.898 69.000 0.828 0.834
4388.0 9.487 0.799 67.055 0.825 0.629

1.2.2 Matrice de corrélation

data_merge_numeric = data_merge.reset_index()
corr_matrix = data_merge_numeric.corr()
sns.heatmap(corr_matrix, annot=True)

L’inclusion de la variable Max infection rate (taux d’infection maximal) dans la matrice de corrélation met en évidence plusieurs relations intéressantes entre la pandémie et les indicateurs de bien-être.

Interprétation des résultats :

  • PIB par habitant (0.34) et espérance de vie (0.32)
    Corrélations positives modérées : les pays plus riches et en meilleure santé ont enregistré des taux d’infection maximaux plus élevés, ce qui peut s’expliquer par une forte connectivité internationale, une urbanisation importante et une meilleure capacité de dépistage.

  • Soutien social (0.23)
    Corrélation positive faible : l’impact du tissu social sur la propagation initiale du virus reste limité et indirect.

  • Liberté de choix (0.04) et corruption (-0.13)
    Corrélations proches de zéro : aucun lien statistiquement significatif n’est observé avec le taux d’infection maximal.

Conclusion :
La pandémie a davantage touché les pays développés, non pas en raison d’une plus faible résilience, mais en raison de leur forte connectivité internationale et de systèmes de surveillance sanitaire plus efficaces.

1.3 Comparaison des deux approches

Indicateurs liés au COVID-19

Deux indicateurs différents sont utilisés dans cette analyse :

  • Total Cases : représente l’exposition globale à la pandémie.
  • Max infection rate : mesure l’intensité maximale des vagues épidémiques.

Signification :
Ces deux approches sont complémentaires et permettent de mieux comprendre l’impact du COVID-19 sur les indicateurs de bien-être, en distinguant l’ampleur globale de la pandémie et la sévérité des pics d’infection.

2 Regression

2.1 Régression linéaire entre le taux d’infection maximal et les indicateurs de bonheur

fig, axs = plt.subplots(ncols=4, figsize=(20, 5))
oy = np.log(data_merge_numeric["Max infection rate"])
sns.regplot(x = data_merge_numeric['Logged GDP per capita'], y = oy , ax=axs[0])
sns.regplot(x = data_merge_numeric['Social support'], y = oy , ax=axs[1])
sns.regplot(x = data_merge_numeric['Healthy life expectancy'], y = oy , ax=axs[2])
sns.regplot(x = data_merge_numeric['Freedom to make life choices'], y = oy , ax=axs[3])

Afin d’étudier plus en détail les relations observées dans la matrice de corrélation, des régressions linéaires simples ont été réalisées entre le logarithme du taux d’infection maximal (Max infection rate) et plusieurs indicateurs du World Happiness Report.

L’utilisation du logarithme permet de réduire l’influence des valeurs extrêmes et de mieux visualiser les tendances générales présentes dans les données.

Analyse des résultats :

  • Une relation positive est observée entre le taux d’infection maximal et le PIB par habitant.
  • Une tendance similaire apparaît avec l’espérance de vie et le soutien social.
  • La relation avec la liberté de faire des choix de vie semble beaucoup plus faible.

Ces résultats confirment les observations obtenues précédemment à partir de la matrice de corrélation : les pays les plus développés ont souvent enregistré des taux d’infection maximaux plus élevés, probablement en raison de leur forte connectivité internationale et de systèmes de surveillance sanitaire plus performants.

2.2 Régression linéaire multiple

2.2.1 Model 1

2.2.1.1 Variable cible (Y)

Y = merged_data["Ladder score"]

2.2.1.2 Variables explicatives (X)

X = merged_data[["Total Cases", "Logged GDP per capita", "Social support", "Healthy life expectancy", "Freedom to make life choices", "Perceptions of corruption"]]

2.2.1.3 Modèle de régression linéaire multiple

from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X, Y)

print("R² =", model.score(X, Y))
R² = 0.05330684110467143

2.2.1.4 Coefficients du modèle

coef_df = pd.DataFrame({
    "Variable": X.columns,
    "Coefficient": model.coef_
})

coef_df.sort_values(
    "Coefficient",
    ascending=False
)
Variable Coefficient
0 Total Cases 2.144021e-08
3 Healthy life expectancy 3.254310e-15
1 Logged GDP per capita 6.366146e-16
2 Social support 3.888285e-17
4 Freedom to make life choices 1.521642e-17
5 Perceptions of corruption -2.720306e-17

2.2.1.5 Évaluation

from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

X_train, X_test, y_train, y_test = train_test_split(
    X, Y,
    test_size=0.2,
    random_state=42
)

model = LinearRegression()
model.fit(X_train, y_train)

pred = model.predict(X_test)

print("R² :", model.score(X_test, y_test))
print("RMSE :", mean_squared_error(y_test, pred)**0.5)
R² : 0.14910212357733876
RMSE : 0.925932992971965

Le faible R² observé indique que la relation entre les variables explicatives et le score de bonheur n’est pas strictement linéaire. Bien que des corrélations fortes existent individuellement entre certaines variables (PIB, espérance de vie, soutien social), leur combinaison dans un modèle linéaire conduit à un phénomène de redondance (multicolinéarité), réduisant ainsi la capacité explicative globale du modèle.

De plus, l’ajout du nombre total de cas de COVID-19 introduit du bruit plutôt qu’une information explicative pertinente, car cette variable dépend fortement de facteurs externes (population, politique de test, reporting des données) et non directement du bien-être.

2.2.1.6 Graphique réel vs prédit

plt.scatter(y_test, pred, color="blue", label="Données prédites") 

plt.plot(
    [y_test.min(), y_test.max()],
    [y_test.min(), y_test.max()],
    color="red", linestyle="--", label="Prédiction idéale (y = x)"
)

plt.xlabel("Ladder score réel")
plt.ylabel("Ladder score prédit")
plt.title("Valeurs réelles vs prédites")
plt.legend() 
plt.show()

Le graphique montre une forte concentration des points alignés horizontalement autour de la valeur prédite de 5.5, tandis que les valeurs réelles s’étendent de 3.5 à plus de 7. L’écart important entre le nuage de points et la ligne idéale de prédiction (\(y = x\)) met en évidence les limites du modèle actuel.


\(R^2 = 0.149\) : Le coefficient de détermination est très faible. Les variables explicatives utilisées dans ce premier modèle ne permettent d’expliquer qu’environ 15% de la variance du score de bonheur (Ladder score). Les 85% restants sont liés à d’autres facteurs non capturés par ce modèle linéaire simple.

RMSE = 0.926 : L’erreur quadratique moyenne indique qu’en moyenne, les prédictions du modèle s’écartent d’environ 0.93 point par rapport aux valeurs réelles du score de bonheur. Sur une échelle de 0 à 10, cette erreur reste relativement importante.

Conclusion:

Ces résultats suggèrent que la relation entre les variables explicatives et le score de bonheur n’est pas parfaitement linéaire, ou que certaines variables introduisent du bruit dans le modèle, notamment celles liées au contexte COVID-19. Une analyse du second modèle permettra de vérifier si une sélection différente de variables améliore la performance globale de la régression.

2.2.2 Model 2

from sklearn.linear_model import LinearRegression

X = data_merge_numeric[
    [
        'Logged GDP per capita',
        'Social support',
        'Healthy life expectancy',
        'Freedom to make life choices',
        'Perceptions of corruption'
    ]
]

y = np.log(data_merge_numeric["Max infection rate"])

model = LinearRegression()
model.fit(X, y)

print(model.score(X, y))
0.4495277408385362

Les résultats montrent une différence importante entre les deux modèles. Le modèle expliquant le taux d’infection maximal présente une capacité prédictive modérée (R² ≈ 0.45), tandis que celui expliquant le niveau de bonheur est beaucoup plus faible (R² ≈ 0.05).

Cela s’explique par le fait que les variables socio-économiques utilisées ont une influence plus directe et mesurable sur la propagation du COVID-19 que sur un concept multidimensionnel et subjectif comme le bonheur.

V

MADE BY NGUYEN DUC HOANG VIET

PROJET COVID-19 DATA ANALYST

© 2026 NGUYEN Duc Hoang Viet — Tous droits réservés.
Projet COVID-19 Data Analyst using Python
Toute reproduction, diffusion ou utilisation sans autorisation est interdite.