1. Requerimiento

Realizar de un caso de práctico que permita aplicar los conceptos aprendidos hasta la fecha para la resolución de un problema real, como es la predicción del churn en telecomunicaciones.

El dataset contiene datos de clientes que dejaron de utilizar un servicio en un plazo determinado.

1.1 Vamos a crear un modelo predicción del churn. Para ellos vamos a:

  • Hacer un análisis exploratorio con algunas estadísticas básicas

  • Hacer una visualización básica de datos

  • Opcional: realizar preprocesamiento de datos

  • División del conjunto de datos en entrenamiento y validación

  • Opcional: segmentar la base de clientes

  • Uso de algún algoritmo predictivo

  • Selección de las métricas para validar la precisión del modelo

  • Principales causas del churn según el conjunto de datos

  • Presentación de resultados

1.2 Conjunto de datos a utilizar:

  • Vamos a trabajar con un conjunto de datos de Kaggle: https://www.kaggle.com/c/customer- churn-prediction-2020/data

  • El conjunto de datos contiene 4.250 registros.

  • Cada registro contiene 20 características y 1 variable booleana “churn” que indica la clase de la muestra.

  • Las 19 variables de entrada son:

    1. “State” (cadena): Código de 2 letras del estado de residencia del cliente en EE. UU.

    1. “Account_length” (numérico): Número de meses que el cliente ha estado con el proveedor de telecomunicaciones actual

    1. “Area_code” (string=“area_code_AAA”): Donde AAA = código de área de 3 dígitos

    1. “International_plan” (booleano sí/no): El cliente tiene, o no, plan internacional

    1. “Voice_mail_plan” (booleano sí/no): El cliente tiene, o no, plan de correo de voz

    1. “Number_vmail_messages” (numérico): Número de mensajes de correo de voz

    1. “Total_day_minutes” (numérico): Minutos totales de llamadas diarias

    1. “Total_day_calls” (numérico): Minutos totales de llamadas diarias

    1. “Total_day_charge” (numérico): Cargo total de llamadas diurnas

    1. “Total_eve_minutes” (numérico): Minutos totales de llamadas nocturnas

    1. “Total_eve_calls” (numérico): Número total de llamadas nocturnas

    1. “Total_eve_charge” (numérico): Cargo total de llamadas nocturnas

    1. “Total_night_minutes” (numérico): Minutos totales de llamadas nocturnas

    1. “total_night_calls” (numérico): Número total de llamadas nocturnas

    1. “Total_night_charge” (numérico): Cargo total de llamadas nocturnas

    1. “Total_intl_minutes” (numérico): Minutos totales de llamadas internacionales

    1. “Total_intl_calls” (numérico): Número total de llamadas internacionales

    1. “Total_intl_charge” (numérico): Cargo total de llamadas internacionales

    1. “Number_customer_service_calls” (numérico): Número de llamadas al servicio de atención al cliente

  • La variable de salida a predecir es: “Churn” (Booleano sí/no): Rotación de clientes: variable objetivo.

2. Carga de Librerias

Realizamos la carga de bibliotecas esenciales que desempeñarán un papel fundamental en nuestro análisis de datos y modelado predictivo del churn. Cada una de estas bibliotecas cumple con una función específica en nuestro trabajo, desde la manipulación de datos hasta la construcción de modelos y la visualización de resultados.

library(dplyr)
library(tidyr)
library(caTools)
library(ggplot2)
library(randomForest)
library(e1071)

3. Carga de datos

Iniciamos importando los datos de nuestro dataset y lo almacenamos en la variable db_churn. Este dataset contiene información sobre el porcentaje de clientes que dejaron de utilizar un servicio de telecomunicaciones en un plazo determinado.

db_churn <-read.csv('dataset_churn.csv', header=T, na.strings='')

4. Análisis Exploratorio y Estadísticas Básicas:

Comenzamos la exploración detallada de nuestro conjunto de datos con el fin de analizar exhaustivamente todas las variables, destacando aquellas que son más pertinentes para los objetivos descritos en los requerimientos Este primer paso nos brindará una comprensión sólida de la estructura y contenido del conjunto de datos, sentando así las bases para investigaciones más especializadas en el futuro sobre el tema abordado en nuestro dataset que trata sobre la problemática de los clientes que cancelan servicios de suscripción en la industria de las telecomunicaciones.

Para obtener una visión preliminar de la estructura y contenido de los datos, exhibimos las primeras observaciones junto con sus respectivas variables mediante la función head(). Este paso resulta fundamental en nuestro análisis exploratorio, ya que nos posibilita evaluar de manera rápida la distribución de los datos y verificar si han sido importados correctamente.

head(db_churn)
##   state account_length     area_code international_plan voice_mail_plan
## 1    OH            107 area_code_415                 no             yes
## 2    NJ            137 area_code_415                 no              no
## 3    OH             84 area_code_408                yes              no
## 4    OK             75 area_code_415                yes              no
## 5    MA            121 area_code_510                 no             yes
## 6    MO            147 area_code_415                yes              no
##   number_vmail_messages total_day_minutes total_day_calls total_day_charge
## 1                    26             161.6             123            27.47
## 2                     0             243.4             114            41.38
## 3                     0             299.4              71            50.90
## 4                     0             166.7             113            28.34
## 5                    24             218.2              88            37.09
## 6                     0             157.0              79            26.69
##   total_eve_minutes total_eve_calls total_eve_charge total_night_minutes
## 1             195.5             103            16.62               254.4
## 2             121.2             110            10.30               162.6
## 3              61.9              88             5.26               196.9
## 4             148.3             122            12.61               186.9
## 5             348.5             108            29.62               212.6
## 6             103.1              94             8.76               211.8
##   total_night_calls total_night_charge total_intl_minutes total_intl_calls
## 1               103              11.45               13.7                3
## 2               104               7.32               12.2                5
## 3                89               8.86                6.6                7
## 4               121               8.41               10.1                3
## 5               118               9.57                7.5                7
## 6                96               9.53                7.1                6
##   total_intl_charge number_customer_service_calls churn
## 1              3.70                             1    no
## 2              3.29                             0    no
## 3              1.78                             2    no
## 4              2.73                             3    no
## 5              2.03                             3    no
## 6              1.92                             0    no

4.1 Resumen estadístico

Aplicamos la función summary() con el propósito de generar un resumen estadístico de nuestro conjunto de datos. Este resumen nos ofrecerá una visión global de las estadísticas descriptivas de cada variable, permitiéndonos comprender de manera más completa la distribución y las características de nuestros datos. En este análisis, se incluyen medidas descriptivas cruciales como la media, mediana, valor mínimo, valor máximo y cuartiles asociados a cada variable.

# Resumen estadístico
summary(db_churn)
##     state           account_length   area_code         international_plan
##  Length:4250        Min.   :  1.0   Length:4250        Length:4250       
##  Class :character   1st Qu.: 73.0   Class :character   Class :character  
##  Mode  :character   Median :100.0   Mode  :character   Mode  :character  
##                     Mean   :100.2                                        
##                     3rd Qu.:127.0                                        
##                     Max.   :243.0                                        
##  voice_mail_plan    number_vmail_messages total_day_minutes total_day_calls 
##  Length:4250        Min.   : 0.000        Min.   :  0.0     Min.   :  0.00  
##  Class :character   1st Qu.: 0.000        1st Qu.:143.3     1st Qu.: 87.00  
##  Mode  :character   Median : 0.000        Median :180.4     Median :100.00  
##                     Mean   : 7.632        Mean   :180.3     Mean   : 99.91  
##                     3rd Qu.:16.000        3rd Qu.:216.2     3rd Qu.:113.00  
##                     Max.   :52.000        Max.   :351.5     Max.   :165.00  
##  total_day_charge total_eve_minutes total_eve_calls total_eve_charge
##  Min.   : 0.00    Min.   :  0.0     Min.   :  0.0   Min.   : 0.00   
##  1st Qu.:24.36    1st Qu.:165.9     1st Qu.: 87.0   1st Qu.:14.10   
##  Median :30.68    Median :200.7     Median :100.0   Median :17.06   
##  Mean   :30.64    Mean   :200.2     Mean   :100.2   Mean   :17.02   
##  3rd Qu.:36.75    3rd Qu.:233.8     3rd Qu.:114.0   3rd Qu.:19.87   
##  Max.   :59.76    Max.   :359.3     Max.   :170.0   Max.   :30.54   
##  total_night_minutes total_night_calls total_night_charge total_intl_minutes
##  Min.   :  0.0       Min.   :  0.00    Min.   : 0.000     Min.   : 0.00     
##  1st Qu.:167.2       1st Qu.: 86.00    1st Qu.: 7.522     1st Qu.: 8.50     
##  Median :200.4       Median :100.00    Median : 9.020     Median :10.30     
##  Mean   :200.5       Mean   : 99.84    Mean   : 9.024     Mean   :10.26     
##  3rd Qu.:234.7       3rd Qu.:113.00    3rd Qu.:10.560     3rd Qu.:12.00     
##  Max.   :395.0       Max.   :175.00    Max.   :17.770     Max.   :20.00     
##  total_intl_calls total_intl_charge number_customer_service_calls
##  Min.   : 0.000   Min.   :0.00      Min.   :0.000                
##  1st Qu.: 3.000   1st Qu.:2.30      1st Qu.:1.000                
##  Median : 4.000   Median :2.78      Median :1.000                
##  Mean   : 4.426   Mean   :2.77      Mean   :1.559                
##  3rd Qu.: 6.000   3rd Qu.:3.24      3rd Qu.:2.000                
##  Max.   :20.000   Max.   :5.40      Max.   :9.000                
##     churn          
##  Length:4250       
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Utilizamos la función glimpse() con el propósito de obtener información crucial de nuestro conjunto de datos, incluyendo el tipo de datos y algunas observaciones iniciales. Esta acción nos proporciona una perspectiva adicional para comprender la composición de nuestro conjunto de datos, al mismo tiempo que facilita la identificación de posibles valores nulos y el reconocimiento de las características de las variables.

glimpse(db_churn)
## Rows: 4,250
## Columns: 20
## $ state                         <chr> "OH", "NJ", "OH", "OK", "MA", "MO", "LA"…
## $ account_length                <int> 107, 137, 84, 75, 121, 147, 117, 141, 65…
## $ area_code                     <chr> "area_code_415", "area_code_415", "area_…
## $ international_plan            <chr> "no", "no", "yes", "yes", "no", "yes", "…
## $ voice_mail_plan               <chr> "yes", "no", "no", "no", "yes", "no", "n…
## $ number_vmail_messages         <int> 26, 0, 0, 0, 24, 0, 0, 37, 0, 0, 0, 0, 0…
## $ total_day_minutes             <dbl> 161.6, 243.4, 299.4, 166.7, 218.2, 157.0…
## $ total_day_calls               <int> 123, 114, 71, 113, 88, 79, 97, 84, 137, …
## $ total_day_charge              <dbl> 27.47, 41.38, 50.90, 28.34, 37.09, 26.69…
## $ total_eve_minutes             <dbl> 195.5, 121.2, 61.9, 148.3, 348.5, 103.1,…
## $ total_eve_calls               <int> 103, 110, 88, 122, 108, 94, 80, 111, 83,…
## $ total_eve_charge              <dbl> 16.62, 10.30, 5.26, 12.61, 29.62, 8.76, …
## $ total_night_minutes           <dbl> 254.4, 162.6, 196.9, 186.9, 212.6, 211.8…
## $ total_night_calls             <int> 103, 104, 89, 121, 118, 96, 90, 97, 111,…
## $ total_night_charge            <dbl> 11.45, 7.32, 8.86, 8.41, 9.57, 9.53, 9.7…
## $ total_intl_minutes            <dbl> 13.7, 12.2, 6.6, 10.1, 7.5, 7.1, 8.7, 11…
## $ total_intl_calls              <int> 3, 5, 7, 3, 7, 6, 4, 5, 6, 5, 2, 5, 9, 4…
## $ total_intl_charge             <dbl> 3.70, 3.29, 1.78, 2.73, 2.03, 1.92, 2.35…
## $ number_customer_service_calls <int> 1, 0, 2, 3, 3, 0, 1, 0, 4, 0, 1, 3, 4, 1…
## $ churn                         <chr> "no", "no", "no", "no", "no", "no", "no"…

4.2 Estructura del Dataset

Con el objetivo de adentrarnos un poco más en nuestro dataset para la estimación del el porcentaje de clientes que dejaron de utilizar un servicio en un plazo determinado, ejecutamos la función str() que nos muestra la estructura completa del conjunto de datos, indicandonos el tipo de datos y la longitud de cada variable

  str(db_churn)
## 'data.frame':    4250 obs. of  20 variables:
##  $ state                        : chr  "OH" "NJ" "OH" "OK" ...
##  $ account_length               : int  107 137 84 75 121 147 117 141 65 74 ...
##  $ area_code                    : chr  "area_code_415" "area_code_415" "area_code_408" "area_code_415" ...
##  $ international_plan           : chr  "no" "no" "yes" "yes" ...
##  $ voice_mail_plan              : chr  "yes" "no" "no" "no" ...
##  $ number_vmail_messages        : int  26 0 0 0 24 0 0 37 0 0 ...
##  $ total_day_minutes            : num  162 243 299 167 218 ...
##  $ total_day_calls              : int  123 114 71 113 88 79 97 84 137 127 ...
##  $ total_day_charge             : num  27.5 41.4 50.9 28.3 37.1 ...
##  $ total_eve_minutes            : num  195.5 121.2 61.9 148.3 348.5 ...
##  $ total_eve_calls              : int  103 110 88 122 108 94 80 111 83 148 ...
##  $ total_eve_charge             : num  16.62 10.3 5.26 12.61 29.62 ...
##  $ total_night_minutes          : num  254 163 197 187 213 ...
##  $ total_night_calls            : int  103 104 89 121 118 96 90 97 111 94 ...
##  $ total_night_charge           : num  11.45 7.32 8.86 8.41 9.57 ...
##  $ total_intl_minutes           : num  13.7 12.2 6.6 10.1 7.5 7.1 8.7 11.2 12.7 9.1 ...
##  $ total_intl_calls             : int  3 5 7 3 7 6 4 5 6 5 ...
##  $ total_intl_charge            : num  3.7 3.29 1.78 2.73 2.03 1.92 2.35 3.02 3.43 2.46 ...
##  $ number_customer_service_calls: int  1 0 2 3 3 0 1 0 4 0 ...
##  $ churn                        : chr  "no" "no" "no" "no" ...

Al igual que los resultados previos al ejecutar la función glimpse(), nuestro conjunto de datos comprende información detallada sobre diversas características de cuentas telefónicas, abarcando aspectos como el estado, duración de la cuenta, código de área, planes internacionales, servicios de correo de voz, mensajes de voz, y más. Entre estas variables, algunas se destacan por ser categóricas y que representaremos como factores, dado que tienen un número limitado de valores únicos, como es el caso de plan_internacional, y plan_correo_voz, entre otras. Este aspecto será abordado en pasos posteriores de nuestro análisis.

4.3 Verificación de Datos Faltantes

# Verificar valores perdidos
sapply(db_churn, function(x) sum(is.na(x)))
##                         state                account_length 
##                             0                             0 
##                     area_code            international_plan 
##                             0                             0 
##               voice_mail_plan         number_vmail_messages 
##                             0                             0 
##             total_day_minutes               total_day_calls 
##                             0                             0 
##              total_day_charge             total_eve_minutes 
##                             0                             0 
##               total_eve_calls              total_eve_charge 
##                             0                             0 
##           total_night_minutes             total_night_calls 
##                             0                             0 
##            total_night_charge            total_intl_minutes 
##                             0                             0 
##              total_intl_calls             total_intl_charge 
##                             0                             0 
## number_customer_service_calls                         churn 
##                             0                             0

Como podemos apreciar, todas las variables en el conjunto de datos están completamente diligenciadas, ya que no se registran valores faltantes en ninguna de ellas. Este hecho resulta ventajoso para nuestro análisis, ya que no sería necesario llevar a cabo la imputación de datos faltantes durante el proceso de análisis.

5. Visualización Básica de Datos:

En este apartado, nos enfocamos en la visualización inicial de nuestro conjunto de datos, específicamente para entender la distribución de las variables numéricas y explorar las proporciones de la variable objetivo.

# Visualizar histogramas de las variables numéricas
db_churn %>%
  select_if(is.numeric) %>%
  gather() %>%
  ggplot(aes(value)) +
  geom_histogram() +
  facet_wrap(~ key, scales = "free") +
  theme_minimal()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Mediante los histogramas anteriores buscamos identificar la forma de las distribuciones de las variables numéricas, lo que es esencial para comprender la variabilidad en los datos.

# Visualizar proporciones de la variable objetivo
db_churn %>%
  ggplot(aes(x = churn, fill = churn)) +
  geom_bar() +
  theme_minimal()

Vizualizamos la proporción de casos de “churn” y “no churn”, para tener una idea inicial de la distribución de la variable objetivo e ir indagando sobre esta durante el análisis

6. Preprocesamiento de Datos

Para simplificar la manipulación de los datos y agilizar la implementación de modelos predictivos, convertimos las varibales categóricas a factores, así logramos fortaleces nuestro conjunto de datos mientra nos adentramos en el análisis

# Convertir las variables categóricas a factores
db_churn$state <- as.factor(db_churn$state)
db_churn$area_code <- as.factor(db_churn$area_code)
db_churn$international_plan <- as.factor(db_churn$international_plan)
db_churn$voice_mail_plan <- as.factor(db_churn$voice_mail_plan)
db_churn$churn <- as.factor(db_churn$churn)

# Verificar la estructura actualizada
str(db_churn)
## 'data.frame':    4250 obs. of  20 variables:
##  $ state                        : Factor w/ 51 levels "AK","AL","AR",..: 36 32 36 37 20 25 19 50 16 40 ...
##  $ account_length               : int  107 137 84 75 121 147 117 141 65 74 ...
##  $ area_code                    : Factor w/ 3 levels "area_code_408",..: 2 2 1 2 3 2 1 2 2 2 ...
##  $ international_plan           : Factor w/ 2 levels "no","yes": 1 1 2 2 1 2 1 2 1 1 ...
##  $ voice_mail_plan              : Factor w/ 2 levels "no","yes": 2 1 1 1 2 1 1 2 1 1 ...
##  $ number_vmail_messages        : int  26 0 0 0 24 0 0 37 0 0 ...
##  $ total_day_minutes            : num  162 243 299 167 218 ...
##  $ total_day_calls              : int  123 114 71 113 88 79 97 84 137 127 ...
##  $ total_day_charge             : num  27.5 41.4 50.9 28.3 37.1 ...
##  $ total_eve_minutes            : num  195.5 121.2 61.9 148.3 348.5 ...
##  $ total_eve_calls              : int  103 110 88 122 108 94 80 111 83 148 ...
##  $ total_eve_charge             : num  16.62 10.3 5.26 12.61 29.62 ...
##  $ total_night_minutes          : num  254 163 197 187 213 ...
##  $ total_night_calls            : int  103 104 89 121 118 96 90 97 111 94 ...
##  $ total_night_charge           : num  11.45 7.32 8.86 8.41 9.57 ...
##  $ total_intl_minutes           : num  13.7 12.2 6.6 10.1 7.5 7.1 8.7 11.2 12.7 9.1 ...
##  $ total_intl_calls             : int  3 5 7 3 7 6 4 5 6 5 ...
##  $ total_intl_charge            : num  3.7 3.29 1.78 2.73 2.03 1.92 2.35 3.02 3.43 2.46 ...
##  $ number_customer_service_calls: int  1 0 2 3 3 0 1 0 4 0 ...
##  $ churn                        : Factor w/ 2 levels "no","yes": 1 1 1 1 1 1 1 1 2 1 ...

7. División del Conjunto de Datos en Entrenamiento y Validación

Preparamos los conjuntos de datos de entrenamiento y prueba para el modelado predictivo, esta división del conjunto de datos nos asegura que tengamos datos independientes para entrenar el modelo y evaluar así evaluar su rendimiento

# Establecer semilla para reproducibilidad
set.seed(123)

# Dividir el conjunto de datos
split <- sample.split(db_churn$churn, SplitRatio = 0.7)
train_data <- subset(db_churn, split == TRUE)
test_data <- subset(db_churn, split == FALSE)

Al ejecutar el código anterior, creamos las bases necesarias para avanzar en la construcción y evaluación del modelo predictivo, utilizaremos algunos algoritmos de aprendizaje supervisado como Random Forest, Support Vector Machines y Regresión Logística, para luego realizar la comparación entre las métricas que obtendremos y así ver cual modelo se desempeña mejor en la tarea de predicción de la variable objetivo (churn) según nuestro caso de estudio

8. Algoritmos Predictivos

8.1 Random Forest

# Crear el modelo
rf_model <- randomForest(churn ~ ., data = train_data, ntree = 100)

# Realizar predicciones en el conjunto de prueba
rf_predictions <- predict(rf_model, test_data)

# Evaluar la precisión del modelo
rf_conf_matrix <- table(rf_predictions, test_data$churn)
rf_accuracy <- sum(diag(rf_conf_matrix))/sum(rf_conf_matrix)
rf_accuracy
## [1] 0.9537255

8.2 Support Vector Machines (SVM):

# Cargar biblioteca para SVM


# Crear el modelo
svm_model <- svm(churn ~ ., data = train_data, kernel = "linear")

# Realizar predicciones en el conjunto de prueba
svm_predictions <- predict(svm_model, test_data)

# Evaluar la precisión del modelo
svm_conf_matrix <- table(svm_predictions, test_data$churn)
svm_accuracy <- sum(diag(svm_conf_matrix))/sum(svm_conf_matrix)
svm_accuracy
## [1] 0.8596078

8.3 Regresión Logística:

# Crear el modelo
logistic_model <- glm(churn ~ ., data = train_data, family = "binomial")

# Realizar predicciones en el conjunto de prueba
logistic_predictions <- predict(logistic_model, test_data, type = "response")

# Convertir a clase binaria (sí/no) usando un umbral de probabilidad (por ejemplo, 0.5)
logistic_predictions <- ifelse(logistic_predictions > 0.5, "yes", "no")

# Evaluar la precisión del modelo
logistic_conf_matrix <- table(logistic_predictions, test_data$churn)
logistic_accuracy <- sum(diag(logistic_conf_matrix))/sum(logistic_conf_matrix)
logistic_accuracy
## [1] 0.8635294

9. Selección de Métricas para Validar la Precisión del Modelo:

9.1 Resumen

A continuación proporcionamos una visión resumida y comparativa de los resultados obtenidos por cada modelo en el conjunto de validación

# Crear un marco de datos para comparar las métricas
metrics_df <- data.frame(
  Model = c("Random Forest", "SVM", "Logistic Regression"),
  Accuracy = c(rf_accuracy, svm_accuracy, logistic_accuracy)
)

# Visualizar las métricas
print(metrics_df)
##                 Model  Accuracy
## 1       Random Forest 0.9537255
## 2                 SVM 0.8596078
## 3 Logistic Regression 0.8635294

Basándonos en los resultados obtenidos en la tabla anterior, podemos hacer las siguientes comparaciones:

Random Forest (Precisión: 95.37%): Este modelo logró una precisión del 95.37%, lo que significa que el 95.37% de las predicciones fueron correctas. El Random Forest es conocido por su capacidad para manejar conjuntos de datos complejos y variables predictoras, y en este caso, ha demostrado ser altamente preciso.

SVM (Precisión: 85.96%): El modelo SVM alcanzó una precisión del 85.96%, indicando que el 85.96% de las clasificaciones fueron correctas. Aunque es una precisión considerable, podría ser menos eficaz en comparación con el Random Forest en este conjunto de datos específico.

Regresión Logística (Precisión: 86.35%): La Regresión Logística obtuvo una precisión del 86.35%, destacando su capacidad para realizar predicciones precisas en problemas de clasificación binaria. Aunque ligeramente menor que la del Random Forest, la Regresión Logística sigue siendo competitiva y eficiente, especialmente si se busca interpretabilidad del modelo.

9.2 Métrica que mejor se adapta a nuestro caso de estudio

Tras realizar la comparación entre las métricas obtenidas: Random Forest, SVM y Regresión Logística , podemos ver que Random Forest ha mostrado la mayor precisión entre los tres, con un impresionante 95.37%.

Random Forest demostró una habilidad notable para predecir con precisión el porcentaje de clientes que dejaron de utilizar un servicio en un plazo determinado (churn) en comparación con el SVM (85.96%) y la Regresión Logística (86.35%). Por lo tanto, en base a estas métricas de rendimiento, se puede concluir que Random Forest fue el modelo más efectivo para abordar el problema en este conjunto de datos sobre los clientes que dejan de utilizar el servicio de telecomunicaciones.

10. Principales Causas del Churn:

Como último paso pero no menos importante, utilizamos la función importance(), para identificar y visualizar las principales causas del churn según Random Forest (modelo con mejor accuracy según ejercicios anteriores) . Al analizar la importancia de las variables, podemos destacar qué características son más relevantes para predecir si un cliente tiene probabilidades de abandonar el servicio de telecomunicaciones.

importance <- importance(rf_model)
varImpPlot(rf_model)

El orden anterior de las variables refleja la contribución relativa de cada una de estas a la precisión del modelo de Random Forest. Podemos interpretar lo siguiente de las primeras 5 variables según este orden:

total_day_charge:

La carga total del día juega el papel más importante según el modelo aplicatido en este caso de estudio. Esto sugiere que el monto total cargado durante el día tiene un impacto significativo en la predicción de churn

state:

La variable de estado también tiene una importancia significativa. Puede indicar que la ubicación geográfica (estado) juega un papel crucial en la retención de clientes

total_day_minutes:

La duración total de las llamadas durante el día es una variable clave en la predicción de churn.

number_customer_service_calls:

La cantidad de llamadas al servicio al cliente es una variable importante, sugiriendo que la interacción con el servicio al cliente está vinculada al churn

international_plan:

La presencia de un plan internacional también contribuye significativamente a la predicción de churn.

11. Presentación de resultados

En el marco de la gestión empresarial, la retención de clientes es un elemento crucial para el crecimiento sostenible y la salud financiera de una organización. El análisis detallado de churn que hemos llevado a cabo nos proporciona una visión estratégica para impulsar la toma de decisiones orientadas a la retención de clientes.

Más adelante presentamos pasos que realizamos y algunos hallazgos clave:

1- Realizamos una exploración inicial de conjunto de datos, analizando las distribuciones de variables clave, acción que nos proporcionó una comprensión detallada del comportamiento de los clientes.

3- Evaluación del Modelo: Implementamos tres modelos de predicción diferentes (Random Forest, SVM y Regresión Logística), evaluando su precisión en la predicción del churn. El modelo Random Forest mostró la mayor precisión, alcanzando un impresionante 95.37%.

11.1 Variables Influyentes: Identificamos las variables más influyentes en la predicción de churn:

  • Carga Diurna y Duración de la Cuenta: La carga total de llamadas diurnas (total_day_charge) y el número de meses que el cliente ha estado con el proveedor de telecomunicaciones actual (account_length) son factores cruciales en la predicción del churn. Recomendamos una atención especial a la facturación diurna y la personalización de estrategias según la duración de la cuenta de los clientes.

  • Importancia Geográfica: El factor geográfico, representado por la variable state, ha mostrado ser significativo en el análisis. Sugerimos personalizar enfoques y ofertas según las características y necesidades específicas de cada región.

  • Interacción con el Servicio al Cliente: La cantidad de llamadas al servicio al cliente (number_customer_service_calls) se destaca como un indicador crítico de churn. Una gestión proactiva y eficiente de las interacciones del servicio al cliente puede tener un impacto directo en la retención.

11.2 Recomendaciones Estratégicas:

  • Personalización de Ofertas:

    Para futuras ofertas utilizar la información de carga diurna, duración de la cuenta y ubicación geográfica para personalizar estas y ofrecer promociones. La personalización puede aumentar la satisfacción del cliente y reducir la probabilidad de churn.

  • Enfoque Regional:

    Adoptar un enfoque regional al diseñar estrategias de retención. Las diferencias geográficas pueden requerir tácticas específicas para abordar las expectativas y necesidades locales.

  • Optimización del Servicio al Cliente:

    Implementar medidas para reducir la necesidad de múltiples llamadas al servicio al cliente. La mejora en la eficiencia y la resolución de problemas tiene un impacto significativo en la retención.

11.3 Beneficios Potenciales:

  • Reducción de Pérdida de Clientes:

    Implementar estrategias personalizadas puede contribuir a una reducción sustancial en la pérdida de clientes.

  • Aumento de Satisfacción del Cliente:

    Tener siempre pendiente que la personalización y la atención a las necesidades específicas pueden elevar la satisfacción del cliente, fomentando la lealtad.

  • Eficiencia Operativa:

    Optimizar del servicio al cliente puede conducir a una eficiencia operativa mejorada y reducir la carga en los recursos de atención al cliente.

12. Conclusión

En la resolución de este caso de estudio, hemos proporcionado una guía práctica y clara para abordar los desafíos de la rotación de clientes, con un enfoque específico en la implementación de modelos de predicción como Random Forest. La efectiva aplicación de estas estrategias puede influir positivamente en la salud global del negocio y fortalecer las relaciones a largo plazo con los clientes, mejorando así la retención y contribuyendo al éxito sostenible de la empresa.