Dans cette étape, nous quittons la statistique univariée pour explorer les relations complexes entre de multiples variables simultanément.
L’Analyse en Composantes Principales (ACP) est une méthode de Machine Learning (apprentissage non supervisé) qui va nous permettre de :
L’algorithme de l’ACP obéit à des règles mathématiques strictes : il nécessite des données strictement numériques (continues) et sans valeurs manquantes (NA).
Nous isolons donc les trois grandes familles de caractéristiques de notre portefeuille :
# Chargement des librairies
library(dplyr)
library(FactoMineR)
library(factoextra)
# Chargement de la base globale
contrats_globaux <- readRDS("contrats_exploration_ok.rds")
# Sélection des variables continues pertinentes
data_acp <- contrats_globaux %>%
select(
drv1Age, drv1DriveLicenceAge, # Profil du conducteur (Âge et Permis)
vhAge, vhWeight, vhDIN, vhValue, # Caractéristiques du véhicule (Âge, Poids, Puissance, Valeur)
ctDeduc, COT_AssBase, claimsAnt # Données du contrat (Franchise, Prime de base, Antécédents)
) %>%
tidyr::drop_na() # Suppression des lignes contenant des NA
# Vérification
print("--- DIMENSIONS AVANT L'ACP ---")## [1] "--- DIMENSIONS AVANT L'ACP ---"
## Nombre d'individus (lignes) : 301437
## Nombre de variables (colonnes) : 9
Nous appliquons l’algorithme d’Analyse en Composantes Principales via
la fonction PCA() du package FactoMineR. Une
étape cruciale de ce calcul est le paramètre
scale.unit = TRUE. En effet, nos variables ayant des unités
et des échelles radicalement différentes (des années, des kilos, des
euros), il est indispensable de les centrer et de les réduire pour
qu’elles aient toutes le même poids dans le modèle.
Le premier résultat graphique à analyser est l’éboulis des valeurs propres. Il nous indique le pourcentage d’information (la variance) résumé par chaque nouvelle dimension créée.
# Exécution de l'ACP
res_acp <- PCA(data_acp, scale.unit = TRUE, ncp = 5, graph = FALSE)
# Visualisation de la variance expliquée (Éboulis des valeurs propres)
graph_vp <- fviz_eig(res_acp,
addlabels = TRUE,
ylim = c(0, 40),
barfill = "#3498db",
barcolor = "#2980b9",
main = "Éboulis des valeurs propres (Variance expliquée)",
xlab = "Dimensions (Axes principaux)",
ylab = "Pourcentage de variance")
# Affichage du graphique
print(graph_vp)## eigenvalue percentage of variance cumulative percentage of variance
## comp 1 2.0225421 22.472690 22.47269
## comp 2 1.8055625 20.061806 42.53450
## comp 3 1.2770541 14.189490 56.72399
## comp 4 1.0008731 11.120812 67.84480
## comp 5 0.9991371 11.101524 78.94632
## comp 6 0.8618801 9.576445 88.52277
Le tableau des valeurs propres nous permet de sélectionner le nombre d’axes pertinents à retenir pour notre analyse :
Le cercle des corrélations projette nos 9 variables initiales sur le premier plan factoriel (Axes 1 et 2). * Des flèches proches (formant un angle aigu) indiquent des variables fortement corrélées positivement. * Des flèches opposées indiquent une corrélation négative. * Des flèches formant un angle droit (90°) indiquent des variables indépendantes.
# Création du cercle des corrélations avec factoextra
graph_var <- fviz_pca_var(res_acp,
col.var = "contrib", # On colore selon la contribution de la variable à l'axe
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), # Du bleu (faible) au rouge (fort)
repel = TRUE, # Évite la superposition des étiquettes (très pratique !)
title = "Cercle des Corrélations des variables d'Assurance (Axes 1 & 2)")
print(graph_var)# ASTUCE POUR NOTRE BINÔME : On extrait les coordonnées exactes pour les analyser ensemble
print("--- COORDONNÉES DES VARIABLES SUR L'AXE 1 ---")## [1] "--- COORDONNÉES DES VARIABLES SUR L'AXE 1 ---"
## drv1Age drv1DriveLicenceAge vhAge vhWeight
## 0.99 0.99 0.14 -0.02
## vhDIN vhValue ctDeduc COT_AssBase
## -0.04 -0.08 0.00 0.21
## claimsAnt
## -0.01
## [1] "--- COORDONNÉES DES VARIABLES SUR L'AXE 2 ---"
## drv1Age drv1DriveLicenceAge vhAge vhWeight
## 0.06 0.06 -0.22 0.64
## vhDIN vhValue ctDeduc COT_AssBase
## 0.84 0.78 0.01 0.13
## claimsAnt
## 0.00
La projection des variables sur le premier plan factoriel révèle une structure bipartite extrêmement nette dans le portefeuille d’ENSAssuRances :
Au lieu d’afficher 300 000 points superposés qui rendraient le graphique illisible, nous utilisons une carte de densité spatiale. Plus la couleur est foncée, plus la concentration d’assurés partageant le même profil est forte.
library(ggplot2)
library(factoextra) # On le recharge ici pour éviter l'erreur !
# 1. Extraction des coordonnées exactes des 300 000 individus sur les axes 1 et 2
coord_ind <- as.data.frame(res_acp$ind$coord)
# 2. Création de la carte de densité (Heatmap 2D)
graph_ind_pro <- ggplot(coord_ind, aes(x = Dim.1, y = Dim.2)) +
# stat_density_2d crée de belles zones de couleurs selon la concentration
stat_density_2d(aes(fill = ..level..), geom = "polygon", color = "white", linewidth = 0.1) +
scale_fill_gradient(low = "#ecf0f1", high = "#2c3e50", name = "Densité\nd'assurés") +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
geom_vline(xintercept = 0, linetype = "dashed", color = "red") +
labs(
title = "Concentration des profils d'assurés (Plan Factoriel)",
subtitle = "Lecture : Plus la zone est foncée, plus le nombre de clients est élevé",
x = "Axe 1 : Âge et Expérience du conducteur (22.5%)",
y = "Axe 2 : Puissance et Valeur du véhicule (20.1%)"
) +
theme_minimal()
print(graph_ind_pro)Ce graphique confirme mathématiquement notre lecture : quelles sont les variables qui “tirent” le plus les individus vers la droite/gauche (Axe 1) ou vers le haut/bas (Axe 2) ? La ligne rouge en pointillés représente le seuil de contribution moyenne.
library(gridExtra)
# Barplot des contributions à l'Axe 1 (On utilise bien fviz_contrib du package factoextra)
contrib_axe1 <- fviz_contrib(res_acp, choice = "var", axes = 1,
fill = "#3498db", color = "black",
title = "Ce qui définit l'Axe 1 (Âge)")
# Barplot des contributions à l'Axe 2
contrib_axe2 <- fviz_contrib(res_acp, choice = "var", axes = 2,
fill = "#e67e22", color = "black",
title = "Ce qui définit l'Axe 2 (Véhicule)")
# Affichage côte à côte
grid.arrange(contrib_axe1, contrib_axe2, ncol = 2)