Dataset: Churn for Bank Customers - Rotacion de clientes bancarios
Origen: https://www.kaggle.com/datasets/mathchi/churn-for-bank-customers
#Explicacion del dataset: Este dataset contiene informacion de rotacion de clientes de un banco europeo con presencia en Francia, Alemania y España, en el cual se incluyen algunos datos personales y de productos, tales como: nombre, genero, edad, estado actual de activacion, numero de productos, score de credito, salario y saldo actual.
#install.packages("dplyr")
library(dplyr)
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
#install.packages("readr")
library(readr)
dsChurn <- read_csv("churn.csv")
## Rows: 10000 Columns: 14
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Surname, Geography, Gender
## dbl (11): RowNumber, CustomerId, CreditScore, Age, Tenure, Balance, NumOfPro...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
library(ggplot2)
library(plotly)
##
## Adjuntando el paquete: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
En primera instancia para el analisis de los datos, se identifica cada uno de los campos que componen el dataset para poder entender su estructura y emitir analisis basados en su contenido.
head(dsChurn,5)
## # A tibble: 5 × 14
## RowNumber CustomerId Surname CreditScore Geography Gender Age Tenure Balance
## <dbl> <dbl> <chr> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
## 1 1 15634602 Hargra… 619 France Female 42 2 0
## 2 2 15647311 Hill 608 Spain Female 41 1 83808.
## 3 3 15619304 Onio 502 France Female 42 8 159661.
## 4 4 15701354 Boni 699 France Female 39 1 0
## 5 5 15737888 Mitche… 850 Spain Female 43 2 125511.
## # ℹ 5 more variables: NumOfProducts <dbl>, HasCrCard <dbl>,
## # IsActiveMember <dbl>, EstimatedSalary <dbl>, Exited <dbl>
#Composicion de la poblacion de clientes por genero
Se observa que mas del 50 % de clientes que ha tenido el banco son hombres. Sin embargo, la cifra no es muy lejana del porcentaje de clientes que son mujeres, lo que significa que tenemos una poblacion homogenea entre hombres y mujeres.
#Utilizamos el campo genero como variable cualitativa para conocer la cantidad de personas por genero
# Crear el gráfico de torta
tablaGenero <- table(dsChurn$Gender)
porcentGenero <- round(tablaGenero/sum(tablaGenero)*100,2)
etiquetasGenero <- paste(porcentGenero," %")
pie(tablaGenero,
labels = etiquetasGenero,
col = rainbow(4),
main="Distribucion de clientes por genero"
)
legend("topleft",
legend = names(tablaGenero),fill = rainbow(4))
Se observa una mayor concentracion de clientes que se retiraron del banco en los rangos de edad entre los 30 y 50 años de edad. Esta poblacion es susceptible a un analisis mas detallado para conocer los factores que pudieron ocasionar el retiro del banco, entre los cuales se podria asumir que los factores fueron:
-Costos altos de mantenimiento de sus productos.
-Baja rentabilidad sobre su saldo.
-Mala experiencia con la atencion al cliente.
-Baja seguridad informatica en sus canales digitales.
Sin embargo, no contamos con estas causas posibles de retiro, pero si poseemos informacion valida sobre sus productos bancarios, para poder establecer estrategias de recuperacion.
#Agregamos el campo de rango de edad al dataset
dsChurn <- dsChurn %>%
mutate(rango_edad= case_when(
Age < 19 ~ "menor a 19",
Age >= 19 & Age < 30 ~ "19-30",
Age >= 30 & Age < 50 ~ "30-50",
Age >= 50 ~ "mayor a 50"
))
#creamos una tabla con los clientes retirados por rango de edad
dsRangoedadret <- dsChurn %>%
filter(Exited==1)
tbRangoedadRet <- table(dsRangoedadret$rango_edad)
miGraficoBarras <-barplot(tbRangoedadRet, main="Distribucion de clientes retirados por Rango de Edad",
ylab = "cantidad de clientes",
xlab = "Rango de edad",
ylim = c(0,1500),
col = "blue")
#Usamos la funcion text para agregar las etiquetas de datos de cada barra
text(x = miGraficoBarras, y = tbRangoedadRet, labels = tbRangoedadRet, pos = 3, cex = 1.0, col = "black")
Al analizar los saldos en las cuentas de los clientes que se han retirado del banco por pais y edad, observamos lo siguiente:
*Los clientes Alemananes que se encuentran en un rango de edad entre los 30 y 50 años, son mas conservadores pues prefieren no mantener tanto dinero en su cuenta, identificando que los saldos oscilan entre los 70.000 eu y los 150.000 eu.
*Los clientes españoles y franceses poseen saldos que van desde los 50.000 eu hasta los 200.000 eu, pero estan dispersos en diferentes edades, ocasionando que la estrategia de recuperacion sea mas compleja.
miGraficoDisp <- ggplot(data = dsRangoedadret, aes(x = Age, y = Balance)) +
geom_point(color = "orange") +
labs(title = "Edad vs Saldo en cuenta Clientes retirados",
x = "Edad (anos)",
y = "Saldo (EU)") +
facet_wrap(~ Geography) +
theme_gray() +
theme(plot.title = element_text(hjust = 0.5))
miGraficoInteractivo <- ggplotly(miGraficoDisp)
miGraficoInteractivo
Se evidencia que el promedio del score de credito de los clientes españoles que se han retirado del banco estan mas cercanos al promedio de score de clientes del banco, lo cual indica que es una poblacion apropiada para gestionar recuperacion a traves del ofrecimiento de nuevos productos.
promedioCredScore <- mean(dsChurn$CreditScore)
# 1. Creamos el grafico usando la funcion ggplot.
# 2. Guardamos el grafico en una variable, que para este caso se llama grBoxplotScore
grBoxplotScore <- ggplot(dsRangoedadret, aes(Geography,CreditScore,fill=Geography)) +
geom_boxplot() +
geom_hline(yintercept = promedioCredScore, color = "red", size = 1) +
labs(title = "Comportamiento Score en clientes retirados", x = "Country", y = "Score") +
theme_bw() +
theme(plot.title = element_text(hjust = 0.5),
legend.position = "none")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# 3. Usamos la funcion ggplotly para convertir nuestro grafico en interactivo, para ello guardamos el nuevo
# grafico en otra variable, que para nuestro caso se llama grBoxplotScoreInt
grBoxplotScoreInt <- ggplotly(grBoxplotScore)
grBoxplotScoreInt