In this project, I will work with the data of bank customers. The aim of my work is to find out the true reasons of the churn of the clients. Firstly, I made a exploratory analysis of the given variables. Then with the cluster analysis, I divided clients on four groups and using logistic regression predicted the factors of churning for the most unstable groups. Then I formed some recommendations that the bank can use to reduce churn.
Firs of all, I will look at my data.
## still_customer customer_age gender dependent_count
## Length:10127 Min. :26.00 Length:10127 Min. :0.000
## Class :character 1st Qu.:41.00 Class :character 1st Qu.:1.000
## Mode :character Median :46.00 Mode :character Median :2.000
## Mean :46.33 Mean :2.346
## 3rd Qu.:52.00 3rd Qu.:3.000
## Max. :73.00 Max. :5.000
## education_level marital_status income_category card_category
## Length:10127 Length:10127 Length:10127 Length:10127
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## months_on_book total_relationship_count months_inactive_12_mon
## Min. :13.00 Min. :1.000 Min. :0.000
## 1st Qu.:31.00 1st Qu.:3.000 1st Qu.:2.000
## Median :36.00 Median :4.000 Median :2.000
## Mean :35.93 Mean :3.813 Mean :2.341
## 3rd Qu.:40.00 3rd Qu.:5.000 3rd Qu.:3.000
## Max. :56.00 Max. :6.000 Max. :6.000
## contacts_count_12_mon credit_limit total_revolving_bal avg_open_to_buy
## Min. :0.000 Min. : 1438 Min. : 0 Min. : 3
## 1st Qu.:2.000 1st Qu.: 2555 1st Qu.: 359 1st Qu.: 1324
## Median :2.000 Median : 4549 Median :1276 Median : 3474
## Mean :2.455 Mean : 8632 Mean :1163 Mean : 7469
## 3rd Qu.:3.000 3rd Qu.:11068 3rd Qu.:1784 3rd Qu.: 9859
## Max. :6.000 Max. :34516 Max. :2517 Max. :34516
## total_amt_chng_q4_q1 total_trans_amt total_trans_ct total_ct_chng_q4_q1
## Min. :0.0000 Min. : 510 Min. : 10.00 Min. :0.0000
## 1st Qu.:0.6310 1st Qu.: 2156 1st Qu.: 45.00 1st Qu.:0.5820
## Median :0.7360 Median : 3899 Median : 67.00 Median :0.7020
## Mean :0.7599 Mean : 4404 Mean : 64.86 Mean :0.7122
## 3rd Qu.:0.8590 3rd Qu.: 4741 3rd Qu.: 81.00 3rd Qu.:0.8180
## Max. :3.3970 Max. :18484 Max. :139.00 Max. :3.7140
## avg_utilization_ratio churn
## Min. :0.0000 Length:10127
## 1st Qu.:0.0230 Class :character
## Median :0.1760 Mode :character
## Mean :0.2749
## 3rd Qu.:0.5030
## Max. :0.9990
I have a dataset with 21 variables and 10 127 rows. From the summary it became clear that there is some sociodemographic information, the information about the interactions between the banl and the clients and some bank calculations.
Now we I will look at the churn variable. It shows if the customer leaves the bank and stop using their services.
| churn | freq |
|---|---|
| no | 8500 |
| yes | 1627 |
8500 clients decided not to churn, while 1627 customers have churned.
## Warning: `stat(prop)` was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(prop)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
I tried to vizualize and check the percentage of customers leaving. Now I conclude that almost 84 percent of people prefer to stay with the bank, and 16 percent chose to leave.
I want to check how churn relates to personal information about customers.
It is difficult to say from the charts that this or that category of customers is more prone to churn. I need to investigate further.
Let’s look at the relationship between age and time that a person is a client of a bank. Oddities are not visible.
The number of products that the client uses has almost no effect on the churn, but with contacts with the bank, the situation is more interesting. It turns out that the more a client contacts the bank, the higher the provability that he will leave.
Customers who are active every or almost every month are less likely to leave. And the connection between the credit limit and the churn is not visible according to the schedule.
Now we need to do some data processing!
For the subsequent clustering, I decided to leave only 3 variables:
months_on_book - how long the client remains a client of the bank, a very important variable showing their loyalty
contacts_count_12_mon - as I found out above, the number of contacts affects the churn
credit_limit - A variable thanks to which we can roughly understand the financial situation of the client
It is also necessary for the clusterization to normalize the values of the three numeric variables.
clust <- churn %>% dplyr::select(months_on_book, contacts_count_12_mon, credit_limit)
clust$months_on_book <- as.numeric(as.factor(clust$months_on_book))
clust$contacts_count_12_mon <- as.numeric(as.factor(clust$contacts_count_12_mon))
cluster <- scale(clust[,c("months_on_book", "contacts_count_12_mon", "credit_limit")])
In this part we should conduct cluster analysis. Looking at the data, we cannot immediately determine how many clusters we need to split our customers into. In order to understand this, we can use two different methods that can help us determine the required number of groups.
Let’s conduct a preliminary analysis to determine the number of clusters. I will start with the Elbow method. We should plot the explained variation as a function of the number of clusters.
The arc bends around four clusters.
To check this, let’s apply Silhouette analysis.
Based on the results of two tests, it became known that it is necessary to divide our customers into 4 groups.
I will be using the k-means clustering method.
set.seed(125)
clusters_k2 <- kmeans(cluster, centers = 4)
So, we got a plot that shows all our customers, divided into 4 groups. I want to know in which cluster what percentage of churn.
The most unreliable are clusters 3 and 4 - of which the most customers leave. The most loyal is the second cluster, here the least number of customers leave the bank.
Let’s take a look at how the variables I selected are distributed among the clusters.
| cluster | months_on_book | credit_limit |
|---|---|---|
| 1 | 35.77856 | 27984.104 |
| 2 | 35.72045 | 5996.630 |
| 3 | 31.55607 | 5207.278 |
| 4 | 45.17765 | 5575.492 |
The table shows that the clusters differ from each other.
In the first cluster, the average credit limit is much higher, the second ones are the least likely to contact to the bank, the third ones have everything “Normal”, and the fourth ones are the bank’s clients for the longest time.
I would call the first cluster Richers.
The second cluster is the complete opposite of the first one.
Let’s call them Avoiders
The group from which the greatest outflow. Let’s explore in more detail.
Seems pretty usual!
No deviations. There are Usual-Churners!
The cluster with one of the highest churn rate.
The only cluster where age was significant. There are mostly people over forty-five years old.
And age, as it turned out, is the only thing that distinguishes them. Let’s call them Olders.
Let’s compare the clusters!
| Number | Name | Churn |
|---|---|---|
| 1 | Richers | 14.4% |
| 2 | Avoiders | 5.9% |
| 3 | Usual-Churners | 19.1% |
| 4 | Olders | 18.3% |
The most problematic are the last two clusters.
To build a linear regression, we first need to select variables. The most churned custer is the third one, so we will make our model on the data of this cluster.
I decided to use variables connected with the interactions between the bank and the customers.
We also need to divide our data for each model into test and training samples in a ratio of 0.8 to 0.2
set.seed(22)
testing2 = createDataPartition(model3$churn, p = 0.2, list = FALSE)
m3_test = model3[testing2,]
m3_train = model3[-testing2,]
The first step is to build the models and look at their summary.
##
## Call:
## glm(formula = churn ~ ., family = binomial, data = m3_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.4502 -0.6822 -0.5232 -0.3574 2.5090
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.200e+00 3.500e-01 -9.142 < 2e-16 ***
## genderM -1.134e-01 9.372e-02 -1.210 0.2264
## total_relationship_count -3.400e-01 2.937e-02 -11.576 < 2e-16 ***
## months_inactive_12_mon 2.284e-01 4.482e-02 5.095 3.49e-07 ***
## contacts_count_12_mon 5.874e-01 5.113e-02 11.488 < 2e-16 ***
## credit_limit -2.657e-05 1.206e-05 -2.204 0.0275 *
## months_on_book 9.940e-03 7.482e-03 1.328 0.1840
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 3677.7 on 3771 degrees of freedom
## Residual deviance: 3383.3 on 3765 degrees of freedom
## AIC: 3397.3
##
## Number of Fisher Scoring iterations: 4
##
## Call:
## glm(formula = churn ~ total_relationship_count + months_inactive_12_mon +
## contacts_count_12_mon + credit_limit, family = binomial,
## data = m3_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.5772 -0.6852 -0.5259 -0.3584 2.5306
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.896e+00 2.525e-01 -11.466 < 2e-16 ***
## total_relationship_count -3.427e-01 2.933e-02 -11.687 < 2e-16 ***
## months_inactive_12_mon 2.337e-01 4.473e-02 5.226 1.73e-07 ***
## contacts_count_12_mon 5.845e-01 5.104e-02 11.452 < 2e-16 ***
## credit_limit -3.146e-05 1.149e-05 -2.738 0.00617 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 3677.7 on 3771 degrees of freedom
## Residual deviance: 3386.7 on 3767 degrees of freedom
## AIC: 3396.7
##
## Number of Fisher Scoring iterations: 4
Now we have a formula of our model (only statistically significiant variables):
Churn ~ total_relationship_count + months_inactive_12_mon + contacts_count_12_mon + credit_limit
In order to evaluate the model, I need to look at their main values.
## Confusion Matrix and Statistics
##
## Reference
## Prediction no yes
## no 759 166
## yes 5 15
##
## Accuracy : 0.819
## 95% CI : (0.793, 0.8431)
## No Information Rate : 0.8085
## P-Value [Acc > NIR] : 0.2171
##
## Kappa : 0.1155
##
## Mcnemar's Test P-Value : <2e-16
##
## Precision : 0.8205
## Recall : 0.9935
## F1 : 0.8988
## Prevalence : 0.8085
## Detection Rate : 0.8032
## Detection Prevalence : 0.9788
## Balanced Accuracy : 0.5382
##
## 'Positive' Class : no
##
Here we can see that this model gives us the false posive result with 5 observations and false negative result with the 18 cases. Recall is about 99%, that means that the model can successfuly denine 99% of churn. The precision is about 82% and the F1 is 90%. It is also important to notice that the accuracy is equal to 82%.
We schould compare these values with the second model.
## Confusion Matrix and Statistics
##
## Reference
## Prediction no yes
## no 759 166
## yes 5 15
##
## Accuracy : 0.819
## 95% CI : (0.793, 0.8431)
## No Information Rate : 0.8085
## P-Value [Acc > NIR] : 0.2171
##
## Kappa : 0.1155
##
## Mcnemar's Test P-Value : <2e-16
##
## Precision : 0.8205
## Recall : 0.9935
## F1 : 0.8988
## Prevalence : 0.8085
## Detection Rate : 0.8032
## Detection Prevalence : 0.9788
## Balanced Accuracy : 0.5382
##
## 'Positive' Class : no
##
The first model is slightly better than the secon one. I will describe it.
We got the list od the most important variables based on the p-values.
contacts_count_12_mon - With each new contact to the bank, the risk of leaving for the client increases by 1.85.
months_inactive_12_mon - The more inactive months customers have, the more likely they are to leave. Each inactive month increases the risk of leaving by 1.30
credit_limit - the credit limit also affects the likelihood of leaving
total_relationship_count - the number of products a customer owns also increases the risk of quitting.
Based on the data from the model, I have developed a list of recommendations that can help the bank to increase its profits.
Interestingly, one of the most significant variables was the number of contacts. Most likely, the clients turned to the bank to solve any problems that had arisen and, having not received a proper solution from the bank, they preferred to leave. Perhaps the bank should work with the system for processing customer requests: conduct trainings for employees, check the availability of online resources for requests, analyze the number of successfully closed requests.
The bank should monitor the activity of customers. As soon as it becomes clear that the usually active client has not been active for 1-2 months, it should be reminded of itself. For example, push notifications with promotions and special offers for a client are an inexpensive way for a bank to reappear in the client’s field of vision.
Perhaps it is worth paying attention to the sequence in which clients open new products of the bank and carefully check the quality of the last ones since the bigger amunt of prodcts one have, the bigger probability to leave.