Un valor atípico (outlier) es una observación que tiene características diferentes a la mayor parte de los datos, es decir, es numéricamente distante del resto de los datos y puede influir en la inferencia de los mismos, por lo cual es indispensable realizar un análisis exhaustivo para descartar la presencia de estas observaciones y dado que existan realizar el respectivo tratamiento.
La base de datos a analizarse presenta 2037 observaciones y 8 atributos. El proceso de detección de anomalías iniciará con métodos gráficos como histogramas, diagramas de caja y diagramas de dispersión. Primero se comprueba la presencia de atípicos de forma univariante es decir analizando cada variable por sí sola y luego las variables en su conjunto.
| Name | df |
| Number of rows | 2037 |
| Number of columns | 8 |
| _______________________ | |
| Column type frequency: | |
| character | 2 |
| numeric | 6 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| …1 | 0 | 1 | 1 | 4 | 0 | 2037 | 0 |
| Mes | 0 | 1 | 1 | 2 | 0 | 9 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| NRO VISITAS | 0 | 1 | 1.51 | 0.73 | 0.00 | 1 | 1 | 2.00 | 3.00 | ▁▇▁▃▂ |
| Éxito | 0 | 1 | 0.68 | 0.47 | 0.00 | 0 | 1 | 1.00 | 1.00 | ▃▁▁▁▇ |
| CAPITAL | 0 | 1 | 0.78 | 0.41 | 0.00 | 1 | 1 | 1.00 | 1.00 | ▂▁▁▁▇ |
| Eficiencia | 0 | 1 | 0.01 | 0.04 | 0.00 | 0 | 0 | 0.01 | 1.00 | ▇▁▁▁▁ |
| Provincia | 0 | 1 | 12.60 | 5.74 | 1.00 | 9 | 12 | 17.00 | 24.00 | ▂▇▃▇▂ |
| Edad | 0 | 1 | 41.39 | 13.71 | 5.77 | 30 | 41 | 53.00 | 75.99 | ▁▇▇▇▂ |
Histogramas y Gráficos de densidad
Como se puede evidenciar, las variables Éxito, Mes, NRO VISITAS, Provincia y CAPITAL son cualitativas, por lo cual las estableceremos como factor.
df$Éxito <- as.factor(df$Éxito)
df$Provincia <- as.factor(df$Provincia)
df$CAPITAL <- as.factor(df$CAPITAL)
df$Mes <- as.integer(df$Mes)
df$`NRO VISITAS` <- as.factor(df$`NRO VISITAS`)
df %>% select_if(is.factor) %>% gather() %>% ggplot(aes(value)) + geom_bar() + facet_wrap(~key,
scales = "free") + theme(axis.text = element_text(size = 6))En los histogramas se observa que, en el primer caso el histograma de CAPITAL revela que las ventas que se realizan en ciudades que son capitales de pronvincia son alrededor de 3 veces mayores en relación a las ventas en las otras ciudades.
El histograma de Éxito revela que aproximadamente de 3 chips vendidos 1 no es entregado y por último el histograma de Provincia evidencia claramente que la provincia con mayor ventas es Pichincha seguido por Guayas, además no existen registro de ventas en Galápagos.
Por otro lado la empresa realiza hasta 3 visitas al cliente y el gráfico indica que en la mayoría de los casos se realiza una sola visita.
df %>% select_if(is.numeric) %>% gather() %>% ggplot(aes(value)) + geom_density() +
facet_wrap(~key, scales = "free") + theme(axis.text = element_text(size = 6))En cuanto a los atributos numéricos, los datos revelan que los clientes potenciales tienen alrededor de 20 a 65 años, y el cliente promedio tiene aproximadamente 42 años, por otra parte la Eficiencia se concentra en valores muy cercanos a 0, esto es debido a que la Eficiencia está tomada en relación al total de ventas realizadas por provincia y hay provincias en las cuales solo hubo una única venta y no fue entregado y existen provincias en las cuales hay gran cantidad de ventas y el porcentaje de entregados y no entregados difiere.
Por último el Mes refleja que en el periodo analizado las ventas de los priemros meses fueron reduciendo, sin embargo, luego se observa una tendencia creciente.
El gráfico anterior muestra la eficiencia por provincia, es decir cuantos chips fueron entregados(color oscuro) y cuantos no (color claro), evidenciando lo mencionado anteriormente, Cotopaxi es la provincia con mayor eficiencia sin embargo, es una de las provincias con menor registro de ventas, sin embargo lo que si es claro es que en Pichincha que es la provincia con mayor ventas también es una de las provincias con mayor eficiencia.
Mientras que Zamora Chinchipe solo tiene un registro de venta que no fue entregado, sin embargo no se puede asegurar que sea un dato atípico, ya que en las provincias del Oriente se evidencian ventas mínimas.
Con el fin de evidenciar de manera más clara la presencia de atípicos en cada atributo se realizan diagramas de caja.
df <- df %>% mutate(Fecha = ifelse(Mes < 3, paste(1, Mes, 2020, sep = "/"), paste(1,
Mes, 2019, sep = "/")))
df$Fecha <- as.Date(df$Fecha, "%d/%m/%Y")
boxplot(Eficiencia ~ Fecha, data = df)En el diagrama de Caja respecto a la fecha de venta y la eficiencia se observa la presencia de datos atípicos, sin embargo. Como se mencionó anteriormente estos no deberían ser considerados como tal ya que al no tener una proporción igual de ventas en cada provincia podría darse este caso.
Mientras que en el Diagrama de Caja de las otras variables no se evidencian valores atípicos.
Considerando como serie temporal
2019-06-01 2019-07-01 2019-08-01 2019-09-01 2019-10-01 2019-11-01 2019-12-01
0.01038953 0.01086069 0.01238895 0.01330033 0.01259028 0.00761532 0.01127428
2020-01-01 2020-02-01
0.01069186 0.01075157
| Medias Mensuales en Eficiciencia | |
|---|---|
| 2019-06-01 | 0.0104 |
| 2019-07-01 | 0.0109 |
| 2019-08-01 | 0.0124 |
| 2019-09-01 | 0.0133 |
| 2019-10-01 | 0.0126 |
| 2019-11-01 | 0.0076 |
| 2019-12-01 | 0.0113 |
| 2020-01-01 | 0.0107 |
| 2020-02-01 | 0.0108 |
outliers <- AnomalyDetectionVec(as.vector(media_mensual), period = 2, direction = "both",
plot = T)
outliers$plot index anoms
1 6 0.00761532
En este gráfico ya se marca, el valor atípico, este se da en cuanto a la eficiencia de entregas en el mes de noviembre y tiene una eficiencia promedio de 0.0076.
Clustering (Matriz de distancia)
Para efectuar un análisis de agrupamiento en datos mixtos, es necesario establecer una métrica adecuada. En nuestro caso utilizaremos la distancia de gower
Además utilizaremos la librería cluster y en particular la función daisy
# Obtendremos la matriz de distancias mediante la metrica de gower para datos
# mixtos
dissE <- daisy(df %>% select(-c(...1, Fecha)), metric = "gower")
summary(dissE)2073666 dissimilarities, summarized :
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.0000 0.3041 0.3951 0.3987 0.4999 0.9446
Metric : mixed ; Types = I, N, N, N, I, N, I
Number of objects : 2037
'dissimilarity' num [1:2073666] 0.289 0.45 0.322 0.155 0.301 ...
- attr(*, "Size")= int 2037
- attr(*, "Metric")= chr "mixed"
- attr(*, "Types")= chr [1:7] "I" "N" "N" "N" ...
dissE_dist <- as.matrix(dissE)
View(dissE_dist) # Matriz de distancias con la metrica gower
# Aplicaremos la tecnica de particionamiento K-Medoids
cluster <- pam(dissE_dist, diss = T, k = 5)
# Cuantos casos existen en cada cluster
table(cluster$clustering)
1 2 3 4 5
280 688 355 318 396
size max_diss av_diss diameter separation
[1,] 280 0.4551712 0.1857377 0.6589108 0.01302932
[2,] 688 0.3788921 0.1531751 0.5639751 0.01993414
[3,] 355 0.3454941 0.1610204 0.6718978 0.01506379
[4,] 318 0.5276607 0.2197310 0.7083926 0.01502148
[5,] 396 0.4932004 0.2283935 0.8025481 0.01302932
1887
1887
El agrupamiento anterior, se realizó mediante la técnica K-Medoids, y se han generado 5 grupos. Además, del registro 1887 se sospecha una anomalía pues posee la mayor distancia promedio.
Dado que ya se tiene una matriz de distancias se puede aplicar otros métodos de agrupación como son: Knn y lof.
k-nearest neighbors distance (K vecinos cercanos)
num [1:2037, 1:2037] 0 0.289 0.449 0.321 0.155 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:2037] "1" "2" "3" "4" ...
..$ : chr [1:2037] "1" "2" "3" "4" ...
# Calculamos la distancia entre 5 vecinos mas cercanos
df_nn <- get.knn(x, k = 5)
head(df_nn$nn.dist) [,1] [,2] [,3] [,4] [,5]
[1,] 0.08957537 0.1763710 0.3542549 0.5971730 0.6213897
[2,] 2.05245811 2.0679181 2.2214148 2.2279879 2.3849403
[3,] 1.66232272 2.2421136 2.2864988 2.5516570 2.5834765
[4,] 1.48126070 1.5625463 1.7249139 1.9328703 2.0239425
[5,] 0.08972202 0.1777148 0.3470658 0.3470658 0.3487796
[6,] 0.47781665 1.0841930 1.1731367 1.2141292 1.2972085
[1] 0.08972202
[1] 109
| …1 | Mes | NRO VISITAS | Éxito | CAPITAL | Eficiencia | Provincia | Edad | Fecha |
|---|---|---|---|---|---|---|---|---|
| 5 | 6 | 1 | 1 | 1 | 0.0017452 | 17 | 38 | 2019-06-01 |
| 109 | 6 | 1 | 1 | 1 | 0.0020408 | 17 | 39 | 2019-06-01 |
[1] 1887
Es decir que se detecta una anomalia en el registro 1887, como se obtuvo en el análisis previo.
Local Outlier Factor (lof) vs Knn
Se realizará una comparación entre ambos métodos, para esto se normalizará nuestra matriz de distancias, es decir la centramos y reducimos.
x_scaled <- scale(x)
x_nn <- get.knn(x_scaled, k = 5)
x$score_knn <- rowMeans(x_nn$nn.dist)
# Calculate and append LOF as a new column
x$score_lof <- lof(x_scaled, k = 5)
# Find the row location of highest kNN
which.max(x$score_knn)[1] 1887
[1] 1981
Finalmente, se evidencia que analizando datos atípicos locales mediante la funcion lof; se ha detecto al registro 1981 como anomalía.
Patrones y Recomendación:
El valor Atípico detectado mediante el algorimo Knn representa la venta realizada en Zamora Chinchipe y es la única venta que se registra en esta provincia, sin embargo, no se elimina esta observación debido a que en la mayor parte de las provincias de la región amazónica se registran ventas mínimas, esto se debe a la poca cobertura de la telefonía.
Mientras que, el dato atípico encontrado mediante el LOF representa una venta realizada en la provincia de Guayas, por lo cual se procederá a eliminar esta observación ya que no afectaría en la inferencia de los datos; debido a que dicha provincia ocupa el segundo lugar en el ranking de ventas, pero nos podríamos preguntar por qué esta observación si pertenece a una de las provincias con mayores ventas y niveles de eficiencia es detectado como atípico, y esto se debe a que es la única venta que se registra en esta provincia durante el mes de febrero 2020.