#1. Introduction au Clustering L’objectif de cette ultime étape d’analyse est de segmenter notre portefeuille de 301 437 contrats en groupes homogènes (clusters). Cette classification permettra à ENSAssuRances d’adapter sa tarification et ses actions commerciales à des “profils types” d’assurés en s’appuyant sur l’algorithme des K-Means.
##1.1. Préparation et Standardisation des données Les algorithmes de clustering se basent sur le calcul de distances géométriques entre les individus. Il est donc indispensable de :
###N’utiliser que des variables numériques.
####Standardiser (centrer-réduire) ces variables pour que les montants en euros (Valeur du véhicule) n’écrasent pas les petites valeurs (Âge du conducteur).
library(dplyr)
library(cluster)
library(factoextra)
# 1. Chargement de la base
contrats_globaux <- readRDS("contrats_exploration_ok.rds")
# 2. Sélection des variables continues pertinentes
data_cluster <- contrats_globaux %>%
select(
drv1Age, drv1DriveLicenceAge, # Profil humain
vhAge, vhWeight, vhDIN, vhValue, # Profil véhicule
COT_AssBase, claimsAnt # Profil contrat/risque
) %>%
tidyr::drop_na()
# 3. Standardisation (Centrage-Réduction) : ÉTAPE CRUCIALE
data_scaled <- scale(data_cluster)
print("Données standardisées prêtes pour le Machine Learning.")## [1] "Données standardisées prêtes pour le Machine Learning."
La fonction de visualisation de la méthode du coude nécessitant trop de mémoire RAM pour s’exécuter sur 300 000 lignes (risque de saturation géométrique), nous appliquons cette recherche du nombre optimal (\(k\)) sur un échantillon représentatif de 20 000 individus.
library(factoextra)
library(ggplot2)
# 1. Création d'un échantillon représentatif pour éviter l'explosion de la RAM
set.seed(123)
echantillon_coude <- data_scaled[sample(1:nrow(data_scaled), 20000), ]
# 2. Exécution de la méthode du coude sur l'échantillon
graph_coude <- fviz_nbclust(echantillon_coude, kmeans, method = "wss", k.max = 8) +
theme_minimal() +
labs(
title = "Méthode du Coude (Elbow Method)",
subtitle = "Détermination du nombre optimal de clusters (k) sur échantillon",
x = "Nombre de clusters (k)",
y = "Inertie intra-classe (WSS)"
) +
geom_line(color = "#c0392b", linewidth = 1) +
geom_point(color = "#c0392b", size = 3)
print(graph_coude)La méthode du coude nous ayant mathématiquement indiqué que 3 clusters forment la segmentation optimale de notre portefeuille, nous appliquons l’algorithme des K-Means avec \(k=3\) sur l’intégralité de nos 301 437 clients.
Nous calculons ensuite la moyenne des variables initiales pour “faire parler” les clusters et dresser le portrait-robot de chaque segment tarifaire.
# On fixe le nombre optimal de clusters trouvé grâce à la méthode du coude
k_optimal <- 3
# 1. Exécution des K-Means sur les 300 000 clients standardisés
set.seed(123) # Pour garantir les mêmes résultats à chaque fois
kmeans_res <- kmeans(data_scaled, centers = k_optimal, nstart = 25)
# 2. Ajout du numéro de cluster (1, 2 ou 3) à notre base de données
data_profils <- data_cluster %>%
mutate(Cluster = as.factor(kmeans_res$cluster))
# 3. Profilage : Calcul des moyennes des variables brutes pour chaque cluster
profils_moyens <- data_profils %>%
group_by(Cluster) %>%
summarise(
Effectif = n(),
Age_Moyen = round(mean(drv1Age), 1),
Permis_Moyen = round(mean(drv1DriveLicenceAge), 1),
Age_Vehicule = round(mean(vhAge), 1),
Valeur_Vehicule = round(mean(vhValue), 0),
Puissance_DIN = round(mean(vhDIN), 0),
Prime_Moyenne = round(mean(COT_AssBase), 0),
Antecedents = round(mean(claimsAnt), 2)
)
# 4. Affichage du tableau final
print("--- PORTRAIT-ROBOT DES 3 CLUSTERS ---")## [1] "--- PORTRAIT-ROBOT DES 3 CLUSTERS ---"
## # A tibble: 3 × 9
## Cluster Effectif Age_Moyen Permis_Moyen Age_Vehicule Valeur_Vehicule
## <fct> <int> <dbl> <dbl> <dbl> <dbl>
## 1 1 119452 34.7 14.7 11.8 8710
## 2 2 101920 59.1 39.2 12.2 9786
## 3 3 80065 41.2 21.3 10.2 17719
## # ℹ 3 more variables: Puissance_DIN <dbl>, Prime_Moyenne <dbl>,
## # Antecedents <dbl>
## Cluster Effectif Age_Moyen Permis_Moyen Age_Vehicule Valeur_Vehicule
## 1 1 119452 34.7 14.7 11.8 8710
## 2 2 101920 59.1 39.2 12.2 9786
## 3 3 80065 41.2 21.3 10.2 17719
## Puissance_DIN Prime_Moyenne Antecedents
## 1 109 43 0.39
## 2 121 48 0.40
## 3 183 48 0.40
Pour bien comprendre comment nos 3 groupes se séparent mathématiquement, nous les projetons sur un graphique en deux dimensions. Note technique : Pour des raisons d’optimisation de rendu visuel et de légèreté du rapport HTML, cette visualisation est générée sur un échantillon représentatif de 10 000 assurés tirés du K-Means global.
library(factoextra)
# 1. Tirage d'un échantillon de 10 000 individus
set.seed(123)
idx_sample <- sample(1:nrow(data_scaled), 10000)
# 2. Création d'un mini-dataset pour le graphique
data_visu <- data_scaled[idx_sample, ]
clusters_visu <- kmeans_res$cluster[idx_sample]
# 3. Génération du graphique des clusters
graph_clusters <- fviz_cluster(
list(data = data_visu, cluster = clusters_visu),
geom = "point", # Uniquement des points (pas de texte)
ellipse.type = "convex", # Dessine une zone autour de chaque cluster
pointsize = 1.5,
alpha = 0.5, # Légère transparence
palette = c("#27ae60", "#2980b9", "#c0392b"), # Vert, Bleu, Rouge
ggtheme = theme_minimal(),
main = "Cartographie des 3 segments tarifaires (K-Means)",
xlab = "Dimension 1 (Profil Générationnel)",
ylab = "Dimension 2 (Gamme du Véhicule)"
)
print(graph_clusters)L’algorithme des K-Means a identifié avec succès trois segments de clientèle extrêmement nets au sein du portefeuille d’ENSAssuRances. Cette segmentation ne se fait pas sur le risque passé (les antécédents étant lissés autour de 0.40 pour tous), mais sur un double axe Générationnel / Valeur du véhicule.