Data de Bitel empresa de telecomunicaciones

Carga de data

Carga de datos formato csv

data <- read.csv("https://raw.githubusercontent.com/VictorGuevaraP/Mineria-de-datos-2020/master/Desafiliado_miss.csv", sep = ";")

Ahora establecemos la estructura inical de las variable de la data y un resumen de la data total, de la siguente manera:

names (data)
## [1] "Genero"                   "Ocupación"               
## [3] "Plan_Internacional"       "Min_En_Dia"              
## [5] "Min_Internacionales"      "Reclamos"                
## [7] "Llamadas_Internacionales" "Desafiliado"
names (data)[2] = "Ocupacion"
str(data)
## 'data.frame':    3333 obs. of  8 variables:
##  $ Genero                  : Factor w/ 2 levels "Femenino","Masculino": 2 2 2 2 2 2 2 2 1 2 ...
##  $ Ocupacion               : Factor w/ 5 levels "  ","Educación",..: 5 3 2 5 2 4 2 1 3 1 ...
##  $ Plan_Internacional      : Factor w/ 2 levels "no","si": 1 1 1 2 2 2 1 2 1 2 ...
##  $ Min_En_Dia              : num  265 162 243 299 NA ...
##  $ Min_Internacionales     : num  10 13.7 12.2 6.6 10.1 6.3 7.5 7.1 8.7 11.2 ...
##  $ Reclamos                : int  1 1 0 2 3 0 3 0 1 0 ...
##  $ Llamadas_Internacionales: int  3 3 5 7 3 6 7 6 4 5 ...
##  $ Desafiliado             : Factor w/ 2 levels "no","si": 1 1 1 1 1 1 1 1 1 1 ...
summary(data)
##        Genero                    Ocupacion   Plan_Internacional   Min_En_Dia   
##  Femenino :1714                       :332   no:3010            Min.   :  0.0  
##  Masculino:1619   Educación           :745   si: 323            1st Qu.:143.6  
##                   Negocios            :732                      Median :179.9  
##                   Otros               :797                      Mean   :180.0  
##                   Proyectos personales:727                      3rd Qu.:216.7  
##                                                                 Max.   :350.8  
##                                                                 NA's   :216    
##  Min_Internacionales    Reclamos     Llamadas_Internacionales Desafiliado
##  Min.   : 0.00       Min.   :0.000   Min.   : 0.000           no:2850    
##  1st Qu.: 8.50       1st Qu.:1.000   1st Qu.: 3.000           si: 483    
##  Median :10.30       Median :1.000   Median : 4.000                      
##  Mean   :10.24       Mean   :1.563   Mean   : 4.479                      
##  3rd Qu.:12.10       3rd Qu.:2.000   3rd Qu.: 6.000                      
##  Max.   :20.00       Max.   :9.000   Max.   :20.000                      
##  NA's   :138

De acuerdo a ello se establece lo siguiente:

Se tiene 3333 datos de 8 variables

Variables:

  1. Género: Género de los clientes, los cuales cuenta con los siguientes niveles
  • Femenino
  • Masculino
  1. La ocupación: Ocupación de trabajo de los clientes, en ellos tienen 5 niveles los cuales son los siguiente:
  • " " (nivel faltante)
  • Negocios
  • Otros
  • Proyectos personales
  1. Plan_Internacional: Si el cliente cuenta con un plan internacional o no, se detallan dos niveles:
  • si
  • no
  1. Min_En_Dia: Los minutos al día consumidos en llamadas por los clientes.
  2. Min_Internacionales: minutos consumidos en llamadas de tipo internacional. (no especifica el tiempo)
  3. Reclamo: reclamos establecidos por los clientes, las cuales cuentan con 10 niveles.
  • 0 <- “se deberían detallar con factor()”
  • 1 <-
  • 2 <-
  • 3 <-
  • 4 <-
  • 5 <-
  • … 9 <- Por lo tanto se tendría 10 niveles de reclamos.
  1. Llamadas internacionales: la cantidad de llamadas internacionales realizadas.
  2. Desafiliado: si el cliente se encuentra desafiliado o no, de detallan dos niveles:
  • si
  • no

Cambiamos la variables a factor

En la varibale Ocupación, el nivel el cual se encuentra vacio, se cambia como “No_Especificado”. Y en el caso de la variable Reclamos, cambiamos a factor.

data$Ocupacion <- factor(data$Ocupacion, levels = c("Proyectos personales","Negocios","Educación","Otros"," "),
                          labels = c("Proyectos personales","Negocios","Educación","Otros","No_Especificado"))


data$Ocupacion[is.na(data$Ocupacion)] <- "No_Especificado"
data$Reclamos <- as.factor(data$Reclamos)

Comprobamos la la conversión establecida.

Se verifica que en la columna Ocupación, sale el nivel “No_Especificado”. Y en la variable Reclamos, es correcta la conversión a factor.

summary(data)
##        Genero                    Ocupacion   Plan_Internacional   Min_En_Dia   
##  Femenino :1714   Proyectos personales:727   no:3010            Min.   :  0.0  
##  Masculino:1619   Negocios            :732   si: 323            1st Qu.:143.6  
##                   Educación           :745                      Median :179.9  
##                   Otros               :797                      Mean   :180.0  
##                   No_Especificado     :332                      3rd Qu.:216.7  
##                                                                 Max.   :350.8  
##                                                                 NA's   :216    
##  Min_Internacionales    Reclamos    Llamadas_Internacionales Desafiliado
##  Min.   : 0.00       1      :1181   Min.   : 0.000           no:2850    
##  1st Qu.: 8.50       2      : 759   1st Qu.: 3.000           si: 483    
##  Median :10.30       0      : 697   Median : 4.000                      
##  Mean   :10.24       3      : 429   Mean   : 4.479                      
##  3rd Qu.:12.10       4      : 166   3rd Qu.: 6.000                      
##  Max.   :20.00       5      :  66   Max.   :20.000                      
##  NA's   :138         (Other):  35

Exploración de Datos

  • Primero se busca NA’s en la data general.
  • En el siguiente gráfico se puede visualizar, que en dos columnas cuentan con valores NA, se visualiza también la cantidad total de NA’s (Haciendo uso de la librería “mice”)
#install.packages("mice")
library(mice)
## Warning: package 'mice' was built under R version 3.6.3
## 
## Attaching package: 'mice'
## The following objects are masked from 'package:base':
## 
##     cbind, rbind
md.pattern(data)

##      Genero Ocupacion Plan_Internacional Reclamos Llamadas_Internacionales
## 2992      1         1                  1        1                        1
## 203       1         1                  1        1                        1
## 125       1         1                  1        1                        1
## 13        1         1                  1        1                        1
##           0         0                  0        0                        0
##      Desafiliado Min_Internacionales Min_En_Dia    
## 2992           1                   1          1   0
## 203            1                   1          0   1
## 125            1                   0          1   1
## 13             1                   0          0   2
##                0                 138        216 354
  • Se hace uso de otra función en el cual se visualizar el patrón de comportamiento de los NA’s. En este caso hace uso en la libreria “VIM”
library(VIM)
## Warning: package 'VIM' was built under R version 3.6.3
## Loading required package: colorspace
## Loading required package: grid
## Loading required package: data.table
## VIM is ready to use. 
##  Since version 4.0.0 the GUI is in its own package VIMGUI.
## 
##           Please use the package to use the new (and old) GUI.
## Suggestions and bug-reports can be submitted at: https://github.com/alexkowa/VIM/issues
## 
## Attaching package: 'VIM'
## The following object is masked from 'package:datasets':
## 
##     sleep
aggr(data, col=c('green', 'red'),
     ylab = c("Histograma de NAs", "Patrón"))

  • Para más detalle, se muestran los porcentaje de NA’s de la data
apply(is.na(data), 2, mean)
##                   Genero                Ocupacion       Plan_Internacional 
##               0.00000000               0.00000000               0.00000000 
##               Min_En_Dia      Min_Internacionales                 Reclamos 
##               0.06480648               0.04140414               0.00000000 
## Llamadas_Internacionales              Desafiliado 
##               0.00000000               0.00000000
  • También se puede presentar los porcentajes por columna:
mean(is.na(data$Min_En_Dia))
## [1] 0.06480648
mean(is.na(data$Min_Internacionales))
## [1] 0.04140414
  • Histogramas de las variables numéricas
hist(data$Min_Internacionales, main = "Minutos Internacionales", xlab ="Min_Internacionales", ylab = "Frecuencia")

hist(data$Min_En_Dia, main = "Minutos consumidos en el día", xlab ="Min_En_Dia", ylab = "Frecuencia")

hist(data$Llamadas_Internacionales, main = "Cantidad de llamadas realizadas", xlab ="Llamadas_Internacionales", ylab = "Frecuencia")

Gráficos para conocimiento de outliers.

Se puede visualizar en todos los boxplot los siguientes valores: - Primer cuartil: el 25% de los valores son menores o igual a este valor. - Mediana o Segundo Cuartil: Divide en dos partes iguales la distribución. De forma que el 50% de los valores son menores o igual a este valor. - Tercer cuartil: el 75% de los valores son menores o igual a este valor. - Rango Intercuartílico (RIC): Diferencia entre el valor del tercer cuartil y el primer cuartil. - Outlier: Los valores atípicos (outilers en inglés) son aquellos puntos que están mas allá del límite inferior o superior.

par(mfrow = c(2,2))
boxplot(data$Min_En_Dia, main = "Min_En_Dia con outliers", xlab ="Min_En_Dia")$out
##  [1] 332.9 337.4 326.5 350.8 335.5  30.9 334.3 346.8  12.5  25.9   0.0   0.0
## [13]  19.5 329.8   7.9  27.0 345.3   2.6   7.8  18.9  29.9
boxplot(data$Min_Internacionales, main = "Min_Internacionales con outliers", xlab ="Min_Internacionales")$out
##  [1] 20.0 17.6  2.7 18.9  0.0 18.0  2.0  0.0 18.2  0.0  1.3  0.0  0.0  0.0  2.2
## [16] 18.0  0.0 17.9  0.0 18.4  2.0  2.9  3.1 17.6  2.6  0.0  0.0 18.2  0.0 18.0
## [31]  1.1  0.0 18.3  0.0  0.0  2.1  2.1  2.4  2.5  0.0 17.8
boxplot(data$Llamadas_Internacionales, main = "Llamadas_Internacionales con outliers", xlab ="Llamadas_Internacionales")$out
##  [1] 19 15 11 12 13 11 12 11 13 12 11 11 18 11 12 13 12 12 11 15 13 15 11 11 14
## [26] 13 11 13 13 12 11 14 15 18 12 13 11 14 11 12 14 15 12 11 16 11 11 11 11 15
## [51] 11 14 11 11 12 13 11 11 16 13 11 13 11 15 11 12 13 18 12 12 12 11 13 11 13
## [76] 14 20 17

Boxplots en función a otras variables

  • En el gráfico se visualiza la variable Llamadas_Internacionales en función a los Reclamos, también se muestran los valores atípicos de aquellas variables.
#Par, vuelve a la normalidad, el tamaño original
par(mfrow = c(1,1))
boxplot(Llamadas_Internacionales ~ Reclamos,
        data = data,
        main = "Llamadas_Internacionales según los Reclamos ")$out

##  [1] 19 15 11 12 12 12 12 12 13 11 13 15 11 16 11 11 13 13 11 13 11 11 18 15 15
## [26] 13 12 14 18 12 13 11 14 12 11 11 15 14 11 12 11 13 13 11 12 13 18 12 12 13
## [51] 14 20 12 11 13 14 11 13 12 11 11 11 11 11 12 11 17 13 11 14 15 11 15 11 11
## [76] 16 11 11  7
  • En el gráfico se visualiza la variable Min_Internacionales en función a los Reclamos, también se muestran los valores atípicos de aquellas variables.
boxplot(Min_Internacionales ~ Reclamos,
        data = data,
        main = "Min_Internacionales según los Reclamos ")$out

##  [1] 20.0 18.9  0.0  3.3  0.0 17.5  2.1  2.4  2.7 18.0  2.0  0.0 18.2  1.3  0.0
## [16]  0.0 18.0  0.0  2.0  2.6 18.2 18.0 18.3  0.0  2.1  2.5  0.0 17.6  0.0  0.0
## [31] 18.4  2.9  3.1 17.6  0.0  1.1  0.0  2.2  0.0  0.0  0.0 17.8 15.0  5.3  5.9
## [46] 15.8
  • En el gráfico se visualiza la variable Min_En_Dia en función a los Reclamos, también se muestran los valores atípicos de aquellas variables.
boxplot(Min_En_Dia ~ Reclamos,
        data = data,
        main = "Min_En_Dia según los Reclamos ")$out

##  [1] 337.4  34.0 334.3  19.5 329.8   7.9 350.8  30.9 346.8  12.5  25.9  35.1
## [13] 321.3   0.0 326.3 345.3 322.4  18.9 335.5   7.8  27.0   2.6 332.9   0.0
## [25]  46.5 253.7
  • En el gráfico se visualiza la variable Min_Internacionales en función a los Desafiliado, también se muestran los valores atípicos de aquellas variables.
boxplot(Min_Internacionales~ Desafiliado,
        data = data,
        main = "Min_Internacionales los Desafiliados ")$out

##  [1]  2.7 18.9  0.0 18.0  0.0 17.5 18.2  0.0  1.3  0.0  0.0  0.0  2.2 18.0  0.0
## [16]  0.0 18.4  2.0  2.9 17.6  2.6  0.0  0.0 18.2  0.0 18.0  1.1  0.0  0.0  0.0
## [31]  2.1 17.5  2.1  2.4  2.5  0.0 17.8 20.0  2.0
  • En el gráfico se visualiza la variable Min_Internacionales en función a los Ocupación, también se muestran los valores atípicos de aquellas variables.
boxplot(Min_Internacionales ~ Ocupacion,
        data = data,
        main = "Min_Internacionales según la Ocupación ")$out

##  [1] 17.6  2.7  0.0  2.0  0.0 17.5  0.0 18.4  2.0  3.1 17.3 18.0  0.0  2.4  0.0
## [16] 18.9  2.6  0.0  0.0  1.1  0.0  2.1  2.5 20.0  0.0  2.2  0.0 17.6  0.0  0.0
## [31]  2.1  3.5 17.5 18.2  1.3  0.0 18.0 17.9  0.0 17.3  3.4 18.2  3.3 18.3 17.8
## [46]  0.0
  • En el gráfico se visualiza la variable Min_En_Dia en función a los Ocupación, también se muestran los valores atípicos de aquellas variables.
boxplot(Min_En_Dia ~ Ocupacion,
        data = data,
        main = "Min_En_Dia según la Ocupación ")$out

##  [1]   0.0   7.8 350.8 334.3 346.8  19.5 345.3 332.9 337.4 335.5  25.9   0.0
## [13]   2.6 326.5  30.9 315.6 321.6  12.5  35.1   7.9 317.8  40.4 324.7  18.9
## [25]  27.0
  • En el gráfico se visualiza la variable Llamadas_Internacionales en función a los Desafiliado, también se muestran los valores atípicos de aquellas variables.
boxplot(Llamadas_Internacionales ~ Desafiliado,
        data = data,
        main = "Min_Internacionales según los Desafiliados ")$out

##  [1] 19 11 12 13 11 12 13 12 11 11 18 11 12 13 12 15 13 15 11 11 14 13 11 13 13
## [26] 12 14 15 18 12 13 11 14 11 12 14 12 11 16 11 11 11 11 11 11 11 12 13 11 11
## [51] 16 13 13 11 15 11 12 18 12 12 12 11 13 11 13 14 17 15 11 10 12 10 11 10 11
## [76] 15 10 15 10 14 10 10 11 10 13 20

Haciendo uso de la librería ggplot

  • Histograma de Llamadas_Internacionales de acuerdo al Género.
#install.packages("ggplot2")
library(ggplot2)
ggplot(data)+
  geom_histogram(mapping = aes(x=Min_Internacionales, color=Genero))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 138 rows containing non-finite values (stat_bin).

- Histograma de Llamadas_Internacionales de acuerdo al Reclamos

ggplot(data)+
  geom_bar(mapping = aes(x=Llamadas_Internacionales, color=Reclamos))
## Warning: position_stack requires non-overlapping x intervals

Selección de la data

Tomamos en cuenta las variables a patir de la segunda columna, es decir, desde la Ocupación. Ya que en el género no se visualizó mucha variación en si es femenino o masculino.

newdata=data[,2:8]

Limpieza de data

  • 1ro empezamos con la limpieza de los valores atípicos. Para ello creamos una funicón.

Capar los valores extremos, es decir, localizar todo lo que cayera fuera del bigote más arriba o más abajo de 1,5 veces de el rango intercuartilico. Y decidir capar dichas obsevaciones sustituyendolas con el percentil número 5. En el caso de los que están debajo del bigote inferior y con el percentil 95 con los que están por encima del bigote superior.

replace_outliers <- function(x, removeNA = TRUE){
  qrts <- quantile(x, probs = c(0.25, 0.75), na.rm = removeNA)
  caps <- quantile(x, probs = c(.05, 0.95), na.rm = removeNA)
  iqr <- qrts[2]-qrts[1]
  h <- 1.5*iqr
  x[x<qrts[1]-h] <- caps[1]
  x[x>qrts[2]+h] <- caps[2]
  x
}

Es un reemplazo no una imputación, de los valores atípicos

La función como entrada tiene vector numérico como entrada x, que sería la data$columna. Con el parámetro opcional que sería removeNA = TRUE.

  • qrts <- quantile(x, probs = c(0.25, 0.75), na.rm = removeNA)

En primer lugar se obtiene los cuantil es Q1 y Q3 para poder calcular el rango inter cuatulico. Se hace uso de la función quantile para el parametro de entrada x, para obrtener aquellos que están exactamente con probabilidad 0.25 por debajo y 0.75 pordebajo y como segundo parametro na.rm igual a removeNA que se ha pasado.

  • caps <- quantile(x, probs = c(.05, 0.95), na.rm = removeNA)

Obteniendo los valores de caping, los cuales detallamos que si está por debajo del rango intercuartil, se tomará el cuantil número 5 y por encima se tomará el 95, al igual que al cuantil de antes el de x. En este caso con probabilidades .05 y .95 con el mismo segundo parámetro de na.rm = removeNA.

  • iqr <- qrts[2]-qrts[1]

Se calcula el rango intercualtilico. El qrts[2], representa el 95 osea menos del 95 - el del 0.25 qrts[1]. Voy a otener 1,5 veces el rando intercualtil el cual será igual a:

  • h <- 1.5*iqr h, que representa la altura.

  • x[x<qrts[1]-h] <- caps[1]

Reemplazo todo lo que se encuentre en “x”, los valores que se encuentrn por debajo del 1er cuantil - h con el caps número 1

  • x[x>qrts[2]+h] <- caps[2]

Reemplazo todo lo que se encuentre en “x”, los valores que se encuentren por encima del 3er cuantil + h con el caps número 2

  • x

Devuelvo x como valor final de la ejecucuón.

Hacemos uso de la función creada

Las hacemos uso en las variables: Min_Internacionales, Llamadas_Internacionales, Min_En_Dia. En las cuales fueron en dónde se presentaron los valores atípicos.

capped_Min_Internacionales <-replace_outliers(newdata$Min_Internacionales)
capped_Min_En_Dia <-replace_outliers(newdata$Min_En_Dia)
capped_Llamadas_Internacionales <- replace_outliers(newdata$Llamadas_Internacionales)

Hacemos la comprobación de la función.

Se puede visualizar, una comparación con el uso del boxplot, de la data principal seleccionada con la data actual que se tiene sin outliers.

par(mfrow = c(1,2))
boxplot(data$Min_Internacionales, main = "Min_Internacionales con outliers")
boxplot(capped_Min_Internacionales, main = "Min_Internacionales outliers")

boxplot(data$Min_En_Dia, main = "Min_En_Dia con outliers")
boxplot(capped_Min_En_Dia, main = "Min_En_Dia sin outliers")

boxplot(data$Llamadas_Internacionales, main = "Llamadas_Internacionales con outliers")
boxplot(capped_Llamadas_Internacionales, main = "Llamadas_Internacionales sin outliers")

Imputación a los valores NA’s, en toda la data.

Hacemos uso de la función knnImputació. La función rellena todos los valores de NA usando los k Vecinos más cercanos de cada caso con valores de NA. Por defecto utiliza los valores de los vecinos y obtiene una media ponderada (por la distancia al caso) de sus valores para rellenar las incógnitas. Se hace uso de la librería “DMwR”

# install.packages("DMwR")
library(DMwR)
## Loading required package: lattice
## Registered S3 method overwritten by 'xts':
##   method     from
##   as.zoo.xts zoo
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## 
## Attaching package: 'DMwR'
## The following object is masked from 'package:VIM':
## 
##     kNN
dataFinal <- knnImputation(newdata)
  • Comprobación de la imputación en los NA’s
summary(newdata)
##                 Ocupacion   Plan_Internacional   Min_En_Dia   
##  Proyectos personales:727   no:3010            Min.   :  0.0  
##  Negocios            :732   si: 323            1st Qu.:143.6  
##  Educación           :745                      Median :179.9  
##  Otros               :797                      Mean   :180.0  
##  No_Especificado     :332                      3rd Qu.:216.7  
##                                                Max.   :350.8  
##                                                NA's   :216    
##  Min_Internacionales    Reclamos    Llamadas_Internacionales Desafiliado
##  Min.   : 0.00       1      :1181   Min.   : 0.000           no:2850    
##  1st Qu.: 8.50       2      : 759   1st Qu.: 3.000           si: 483    
##  Median :10.30       0      : 697   Median : 4.000                      
##  Mean   :10.24       3      : 429   Mean   : 4.479                      
##  3rd Qu.:12.10       4      : 166   3rd Qu.: 6.000                      
##  Max.   :20.00       5      :  66   Max.   :20.000                      
##  NA's   :138         (Other):  35

Se pueden visualizar los NA’s en las variables

summary(dataFinal)
##                 Ocupacion   Plan_Internacional   Min_En_Dia   
##  Proyectos personales:727   no:3010            Min.   :  0.0  
##  Negocios            :732   si: 323            1st Qu.:146.0  
##  Educación           :745                      Median :179.2  
##  Otros               :797                      Mean   :179.8  
##  No_Especificado     :332                      3rd Qu.:214.4  
##                                                Max.   :350.8  
##                                                               
##  Min_Internacionales    Reclamos    Llamadas_Internacionales Desafiliado
##  Min.   : 0.00       1      :1181   Min.   : 0.000           no:2850    
##  1st Qu.: 8.60       2      : 759   1st Qu.: 3.000           si: 483    
##  Median :10.30       0      : 697   Median : 4.000                      
##  Mean   :10.24       3      : 429   Mean   : 4.479                      
##  3rd Qu.:12.00       4      : 166   3rd Qu.: 6.000                      
##  Max.   :20.00       5      :  66   Max.   :20.000                      
##                      (Other):  35

No se reflejan los NA’s en las variables.

Formato

write.csv(dataFinal, file = "dataFinal.csv")
getwd()
## [1] "D:/VII CICLO/MINERIA DE DATOS/CLASES/SEMANA3/E1"