Dans un environnement où la fidélisation de la clientèle est cruciale pour le secteur financier, ce projet se concentre sur l’analyse des facteurs qui influencent l’attrition des clients d’une banque européenne. Nous examinerons les informations relatives aux comptes de 10,000 clients, en nous penchant sur divers aspects tels que leur solvabilité, leur âge, le solde de leur compte, et leur utilisation des produits bancaires.
Nous visons à identifier les caractéristiques qui sont les plus souvent associées au départ des clients, à évaluer si l’attrition peut être prédite à partir des données disponibles, et à comprendre les différences de comportement entre différents segments de clientèle. Cette analyse permettra de mettre en lumière les défis liés à la rétention de la clientèle dans le secteur bancaire et de proposer des pistes pour améliorer les stratégies de fidélisation et la gestion de la relation client.
# Charger les données depuis le fichier CSV
bank_data <- read.csv("Bank_Churn.csv")
# Afficher les premières lignes du jeu de données
head(bank_data)
## CustomerId Surname CreditScore Geography Gender Age Tenure Balance
## 1 15634602 Hargrave 619 France Female 42 2 0.00
## 2 15647311 Hill 608 Spain Female 41 1 83807.86
## 3 15619304 Onio 502 France Female 42 8 159660.80
## 4 15701354 Boni 699 France Female 39 1 0.00
## 5 15737888 Mitchell 850 Spain Female 43 2 125510.82
## 6 15574012 Chu 645 Spain Male 44 8 113755.78
## NumOfProducts HasCrCard IsActiveMember EstimatedSalary Exited
## 1 1 1 1 101348.88 1
## 2 1 0 1 112542.58 0
## 3 3 1 0 113931.57 1
## 4 2 0 0 93826.63 0
## 5 1 1 1 79084.10 0
## 6 2 1 0 149756.71 1
# Obtenir un résumé descriptif des données
summary(bank_data)
## CustomerId Surname CreditScore Geography
## Min. :15565701 Length:10000 Min. :350.0 Length:10000
## 1st Qu.:15628528 Class :character 1st Qu.:584.0 Class :character
## Median :15690738 Mode :character Median :652.0 Mode :character
## Mean :15690941 Mean :650.5
## 3rd Qu.:15753234 3rd Qu.:718.0
## Max. :15815690 Max. :850.0
## Gender Age Tenure Balance
## Length:10000 Min. :18.00 Min. : 0.000 Min. : 0
## Class :character 1st Qu.:32.00 1st Qu.: 3.000 1st Qu.: 0
## Mode :character Median :37.00 Median : 5.000 Median : 97199
## Mean :38.92 Mean : 5.013 Mean : 76486
## 3rd Qu.:44.00 3rd Qu.: 7.000 3rd Qu.:127644
## Max. :92.00 Max. :10.000 Max. :250898
## NumOfProducts HasCrCard IsActiveMember EstimatedSalary
## Min. :1.00 Min. :0.0000 Min. :0.0000 Min. : 11.58
## 1st Qu.:1.00 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.: 51002.11
## Median :1.00 Median :1.0000 Median :1.0000 Median :100193.91
## Mean :1.53 Mean :0.7055 Mean :0.5151 Mean :100090.24
## 3rd Qu.:2.00 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:149388.25
## Max. :4.00 Max. :1.0000 Max. :1.0000 Max. :199992.48
## Exited
## Min. :0.0000
## 1st Qu.:0.0000
## Median :0.0000
## Mean :0.2037
## 3rd Qu.:0.0000
## Max. :1.0000
# Examiner la structure des données (types de variables, etc.)
str(bank_data)
## 'data.frame': 10000 obs. of 13 variables:
## $ CustomerId : int 15634602 15647311 15619304 15701354 15737888 15574012 15592531 15656148 15792365 15592389 ...
## $ Surname : chr "Hargrave" "Hill" "Onio" "Boni" ...
## $ CreditScore : int 619 608 502 699 850 645 822 376 501 684 ...
## $ Geography : chr "France" "Spain" "France" "France" ...
## $ Gender : chr "Female" "Female" "Female" "Female" ...
## $ Age : int 42 41 42 39 43 44 50 29 44 27 ...
## $ Tenure : int 2 1 8 1 2 8 7 4 4 2 ...
## $ Balance : num 0 83808 159661 0 125511 ...
## $ NumOfProducts : int 1 1 3 2 1 2 2 4 2 1 ...
## $ HasCrCard : int 1 0 1 0 1 1 1 1 0 1 ...
## $ IsActiveMember : int 1 1 0 0 1 0 1 0 1 1 ...
## $ EstimatedSalary: num 101349 112543 113932 93827 79084 ...
## $ Exited : int 1 0 1 0 0 1 0 1 0 0 ...
IdentifiantClient: Identifiant unique du client (non
pertinent pour l’analyse).NomDeFamille: Nom de famille du client (non pertinent
pour l’analyse).ScoreCredit: Score de crédit du client.Geographie: Pays de résidence du client (France,
Espagne, Allemagne).Genre: Genre du client (Masculin, Féminin).Age: Âge du client.Anciennete: Ancienneté du client en tant que membre de
la banque (en années).Solde: Solde du compte du client.NombreDeProduits: Nombre de produits bancaires utilisés
par le client.PossèdeCarteCredit: Indique si le client possède une
carte de crédit (1 = Oui, 0 = Non).EstMembreActif: Indique si le client est un membre
actif (1 = Oui, 0 = Non).SalaireEstimé: Salaire estimé du client.ClientParti: Indique si le client a quitté la banque (1
= Oui, 0 = Non). C’est notre variable cible.# Vérifier s'il y a des valeurs manquantes
sum(is.na(bank_data))
## [1] 0
# Si il y avait des valeurs manquantes, on pourrait les traiter ici.
# Par exemple, on pourrait imputer la moyenne pour les variables numériques
# et la modalité pour les variables catégorielles.
# Mais dans ce cas, il n'y en a pas.
# Convertir les variables catégorielles en facteurs
names(bank_data)[names(bank_data) == "Geography"] <- "Pays"
names(bank_data)[names(bank_data) == "Gender"] <- "Genre"
names(bank_data)[names(bank_data) == "HasCrCard"] <- "PossedeCarteCredit"
names(bank_data)[names(bank_data) == "IsActiveMember"] <- "EstMembreActif"
names(bank_data)[names(bank_data) == "Exited"] <- "ClientParti"
names(bank_data)[names(bank_data) == "CreditScore"] <- "ScoreCredit"
names(bank_data)[names(bank_data) == "Age"] <- "Age"
names(bank_data)[names(bank_data) == "Tenure"] <- "Anciennete"
names(bank_data)[names(bank_data) == "Balance"] <- "SoldeCompte"
names(bank_data)[names(bank_data) == "NumOfProducts"] <- "NombreDeProduits"
names(bank_data)[names(bank_data) == "EstimatedSalary"] <- "SalaireEstime"
bank_data$Pays <- as.factor(bank_data$Pays)
bank_data$Genre <- as.factor(bank_data$Genre)
bank_data$PossedeCarteCredit <- as.factor(bank_data$PossedeCarteCredit)
bank_data$EstMembreActif <- as.factor(bank_data$EstMembreActif)
bank_data$ClientParti <- as.factor(bank_data$ClientParti)
# S'assurer que les variables sont bien des facteurs d'abord
bank_data$Pays <- factor(bank_data$Pays,
levels = c("Germany", "Spain", "France"),
labels = c("Allemagne", "Espagne", "France"))
bank_data$Genre <- factor(bank_data$Genre,
levels = c("Female", "Male"),
labels = c("Feminin", "Masculin"))
bank_data$PossedeCarteCredit <- factor(bank_data$PossedeCarteCredit,
levels = c(0, 1),
labels = c("Non", "Oui"))
bank_data$EstMembreActif <- factor(bank_data$EstMembreActif,
levels = c(0, 1),
labels = c("Non", "Oui"))
bank_data$ClientParti <- factor(bank_data$ClientParti,
levels = c(0, 1),
labels = c("Non", "Oui"))
# Afficher les premières lignes du jeu de données après la traduction
head(bank_data)
## CustomerId Surname ScoreCredit Pays Genre Age Anciennete SoldeCompte
## 1 15634602 Hargrave 619 France Feminin 42 2 0.00
## 2 15647311 Hill 608 Espagne Feminin 41 1 83807.86
## 3 15619304 Onio 502 France Feminin 42 8 159660.80
## 4 15701354 Boni 699 France Feminin 39 1 0.00
## 5 15737888 Mitchell 850 Espagne Feminin 43 2 125510.82
## 6 15574012 Chu 645 Espagne Masculin 44 8 113755.78
## NombreDeProduits PossedeCarteCredit EstMembreActif SalaireEstime ClientParti
## 1 1 Oui Oui 101348.88 Oui
## 2 1 Non Oui 112542.58 Non
## 3 3 Oui Non 113931.57 Oui
## 4 2 Non Non 93826.63 Non
## 5 1 Oui Oui 79084.10 Non
## 6 2 Oui Non 149756.71 Oui
# Examiner la structure des données après la traduction
str(bank_data)
## 'data.frame': 10000 obs. of 13 variables:
## $ CustomerId : int 15634602 15647311 15619304 15701354 15737888 15574012 15592531 15656148 15792365 15592389 ...
## $ Surname : chr "Hargrave" "Hill" "Onio" "Boni" ...
## $ ScoreCredit : int 619 608 502 699 850 645 822 376 501 684 ...
## $ Pays : Factor w/ 3 levels "Allemagne","Espagne",..: 3 2 3 3 2 2 3 1 3 3 ...
## $ Genre : Factor w/ 2 levels "Feminin","Masculin": 1 1 1 1 1 2 2 1 2 2 ...
## $ Age : int 42 41 42 39 43 44 50 29 44 27 ...
## $ Anciennete : int 2 1 8 1 2 8 7 4 4 2 ...
## $ SoldeCompte : num 0 83808 159661 0 125511 ...
## $ NombreDeProduits : int 1 1 3 2 1 2 2 4 2 1 ...
## $ PossedeCarteCredit: Factor w/ 2 levels "Non","Oui": 2 1 2 1 2 2 2 2 1 2 ...
## $ EstMembreActif : Factor w/ 2 levels "Non","Oui": 2 2 1 1 2 1 2 1 2 2 ...
## $ SalaireEstime : num 101349 112543 113932 93827 79084 ...
## $ ClientParti : Factor w/ 2 levels "Non","Oui": 2 1 2 1 1 2 1 2 1 1 ...
Nous allons creuser dans les données des clients de la banque pour comprendre pourquoi certains partent et comment ils se comportent.
En gros, nous voulons comprendre les départs, qui sont les clients, comment ils se comparent selon leur pays et s’il y a des types de clients différents.
Points clés : Attrition, démographie, géographie, segments.
L’idée principale de regarder chaque information client séparément, c’est de voir comment ils sont répartis. Par exemple, combien ont un bon score de crédit ? Quel est le solde moyen ? Où vivent-ils ? En regardant chaque détail un par un, nous se faisons une idée claire de qui sont ces 10,000 clients de la banque européenne, avant de chercher à comprendre pourquoi certains s’en vont.
# Analyse univariée des variables quantitatives continues
summary(bank_data[, c("ScoreCredit", "Age", "SoldeCompte", "SalaireEstime")])
## ScoreCredit Age SoldeCompte SalaireEstime
## Min. :350.0 Min. :18.00 Min. : 0 Min. : 11.58
## 1st Qu.:584.0 1st Qu.:32.00 1st Qu.: 0 1st Qu.: 51002.11
## Median :652.0 Median :37.00 Median : 97199 Median :100193.91
## Mean :650.5 Mean :38.92 Mean : 76486 Mean :100090.24
## 3rd Qu.:718.0 3rd Qu.:44.00 3rd Qu.:127644 3rd Qu.:149388.25
## Max. :850.0 Max. :92.00 Max. :250898 Max. :199992.48
hist(bank_data$ScoreCredit,
main = "Distribution du Score de Crédit",
xlab = "Score de Crédit",
col = "lightblue",
border = "white")
La plupart des scores se situent entre 600 et 700. La distribution est centrée, mais légèrement décalée vers les scores plus bas.
hist(bank_data$Age,
main = "Distribution de l'Âge",
xlab = "Âge",
col = "lightgreen",
border = "white")
On observe une forte concentration autour de 30-40 ans. La distribution est asymétrique à droite, indiquant moins de personnes âgées.
hist(bank_data$SoldeCompte,
main = "Distribution du Solde du Compte",
xlab = "Solde du Compte",
col = "lightcoral",
border = "white")
La majorité des comptes ont un solde très bas, proche de zéro. On observe une deuxième concentration de soldes entre 100 000 et 150 000.
hist(bank_data$SalaireEstime,
main = "Distribution du Salaire Estimé",
xlab = "Salaire Estimé",
col = "lightgoldenrod",
border = "white")
Les salaires estimés sont répartis de manière relativement uniforme sur toute la plage observée.
# Analyse univariée des variables quantitatives discrètes
summary(bank_data[, c("Anciennete", "NombreDeProduits")])
## Anciennete NombreDeProduits
## Min. : 0.000 Min. :1.00
## 1st Qu.: 3.000 1st Qu.:1.00
## Median : 5.000 Median :1.00
## Mean : 5.013 Mean :1.53
## 3rd Qu.: 7.000 3rd Qu.:2.00
## Max. :10.000 Max. :4.00
barplot(table(bank_data$Anciennete),
main = "Distribution de l'Ancienneté",
xlab = "Ancienneté (années)",
ylab = "Nombre de Clients",
col = 'lightblue')
# Visualisation avec un diagramme circulaire
# Calcul des fréquences relatives
tenure_freq <- table(bank_data$Anciennete)
tenure_rel_freq <- prop.table(tenure_freq)
tenure_labels <- paste0(names(tenure_rel_freq), "\n", round(tenure_rel_freq * 100, 1), "%")
# Création du diagramme circulaire
pie(tenure_rel_freq,
labels = tenure_labels,
main = "Distribution de l'Ancienneté",
col = c("#E0F7FA", "#B2EBF2", "#81D4FA", "#4FC3F7", "#ADD8E6", # Light Blue
"#A7D1EB", "#9EC1E0", "#95BBD5", "#8CA6CA", "#8391BF",
"#CCE0CF"),
cex = 0.8) # Ajustement de la taille du texte si nécessaire
# Ajout d'une légende
legend("topright",
legend = names(tenure_rel_freq),
fill = c("#E0F7FA", "#B2EBF2", "#81D4FA", "#4FC3F7", "#ADD8E6", # Light Blue
"#A7D1EB", "#9EC1E0", "#95BBD5", "#8CA6CA", "#8391BF",
"#CCE0CF"),
cex = 0.8)
Les diagrammes montrent que les clients sont répartis de manière assez égale entre les différentes années d’ancienneté. Il n’y a pas de groupe d’ancienneté beaucoup plus grand que les autres.
barplot(table(bank_data$NombreDeProduits),
main = "Distribution du Nombre de Produits",
xlab = "Nombre de Produits",
ylab = "Nombre de Clients",
col = 'lightgreen')
La plupart des clients ont un ou deux produits. Très peu de clients ont trois ou quatre produits.