hllinas2023

1 Librerías

library(aplore3)       #Base de datos para los ejemplos
library(lsm)           #Base de datos para ejemplos y estimaciones del Log-verosimilitud
library(tidyverse)     #Incluye a dplyr y ggplot2
library(stringr)       #Reemplazar caracteres en un data frame
library(outliers)      #outliers::grubbs.test
library(EnvStats)      #EnvStats::rosnerTest
library(DMwR2)         #LOF (Local Outlier Factor)
library(rgl)           #rgl::plot3d

2 Conceptos básicos

La detección de valores atípicos (outliers) en datos es un área importante en estadísticas y análisis de datos. Hay varios métodos para identificar valores atípicos. Un valor se considera atípico si está significativamente por encima o por debajo de ciertos umbrales basados en medidas estadísticas.

En general, los valores atípicos pueden clasificarse en tres categorías:

  1. Valor atípico global: el objeto se desvía significativamente del resto del conjunto de datos.

  2. Valor atípico contextual: el objeto se desvía significativamente en función de un contexto seleccionado. Por ejemplo, 28⁰C es un valor atípico para un invierno en Rusia, pero no lo es en otro contexto. Además, 28⁰C no es un valor atípico para un verano rusoa.

  3. Valor atípico multivariado o colectivo: un subconjunto de objetos de datos se desvía colectivamente de forma significativa del conjunto de datos, aunque los objetos de datos individuales no sean valores atípicos. Son puntos de datos atípicos cuando se consideran simultáneamente varios atributos o dimensiones. Por ejemplo, un gran conjunto de transacciones de la misma acción entre un pequeño grupo en un periodo corto puede considerarse una prueba de manipulación del mercado.

datosCompleto <- lsm::survey
dat <- datosCompleto[,3:10]
attach(dat)

3 Métodos para detectar outliers

En las siguientes secciones se van a explicar varios métodos.

4 Primer método: Histograma

ggplot(dat) +
  aes(x =Age) +
  geom_histogram(bins = 30L, color = "red", fill = "#0c4c8a") +
   facet_wrap(~"Diagrama de caja y bigotes para la edad") +
  theme(legend.position="none") +
  theme_bw(base_size = 11) + # Tamaño de las fuentes
  theme(axis.text.x = element_text(angle = 0#, vjust = 1.0, hjust=1
                                   )
        )  #+

Según el histograma, parece que hay observaciones con valores muy grande en comparación con el resto (véase la barra de la derecha del gráfico).

5 Segundo método: Diagrama de caja y bigotes

5.0.1 El diagrama

Además de los histogramas, los gráficos de caja también son útiles para detectar posibles valores atípicos.

ggplot(dat) +
  aes(x = Age, y = "") +
  geom_boxplot(fill = "blue") +
  xlim(10,32)+
   facet_wrap(~"Diagrama de caja y bigotes para la edad") +
  theme(legend.position="none") +
  theme_bw(base_size = 11) + # Tamaño de las fuentes
  theme(axis.text.x = element_text(angle = 0#, vjust = 1.0, hjust=1
                                   )
        )  #+

Un boxplot ayuda a visualizar una variable cuantitativa mostrando cinco resumen de localización comunes (mínimo, mediana, primer y tercer cuartil y máximo) y cualquier observación que se haya clasificado como presunto valor atípico utilizando el criterio del rango intercuartílico (IQR).

Las observaciones consideradas como posibles valores atípicos por el criterio IQR se muestran como puntos en el boxplot. Según este criterio, hay 4 valores atípicos potenciales (véanse los 4 puntos al lado derecho de la línea horizontal).

Recuerde que el hecho de que una observación se considere un valor atípico potencial según el criterio IQR no significa que deba eliminarla.

Eliminar o mantener un valor atípico depende de:

  1. El contexto de su análisis.

  2. Si las pruebas que va a realizar en el conjunto de datos son robustas o no a los valores atípicos.

  3. Y la distancia entre el valor atípico y las demás observaciones.

5.0.2 Extraer los valores atípicos

También es posible extraer los valores de los posibles valores atípicos basándose en el criterio IQR gracias a la siguiente función:

boxplot.stats(Age)$out
## [1] 24.91 27.88 29.85 28.76

Como se puede ver, hay 3 puntos considerados como valores atípicos potenciales.

###Extraer filas de los valores atípicos

Gracias a la función which() es posible extraer el número de fila correspondiente a estos valores atípicos:

out_box <- boxplot.stats(Age)$out
out_ind_box <- which(Age %in% c(out_box))
out_ind_box
## [1]  19  37 141 383

5.0.3 Imprimir filas de los valores atípicos

Con esta información, ahora puede volver fácilmente a las filas específicas del conjunto de datos para verificarlas, o imprimir todas las variables de estos valores atípicos:

dat[out_ind_box, ]
Gender Like Age Smoke Height Weight BMI School
Male TV 24.91 No 1.65 90 33.05785 Private
Female Network 27.88 Yes 1.63 55 20.70082 Private
Female TV 29.85 No 1.65 88 32.32323 Private
Male Network 28.76 Yes 1.65 54 19.83471 Private

5.0.4 Imprimir texto en el boxplot

También es posible imprimir los valores de los valores atípicos directamente en boxplot con la función mtext():

boxplot(Age, col = "blue",
  xlab = "Age",
  main = "Boxplot of Age", horizontal=TRUE)

mtext(paste("Outliers: ", paste(out_box, collapse = ", ")))

6 Tercer método: Percentiles

Este método de detección de valores atípicos se basa en los percentiles. Con el método de los percentiles, todas las observaciones que se encuentren fuera del intervalo formado por los percentiles 2,5 y 97,5 se considerarán valores atípicos potenciales.

También pueden considerarse otros percentiles, como el 1 y el 99, o el 5 y el 95, para construir el intervalo.

6.0.1 Estimar las cotas del intervalo

Los valores de los percentiles inferior y superior (y, por tanto, los límites inferior y superior del intervalo) pueden calcularse con la función quantile():

low_perc <- quantile(Age, 0.025, na.rm=TRUE)
low_perc
##     2.5% 
## 12.87925
up_perc <- quantile(Age, 0.975, na.rm=TRUE)
up_perc
##   97.5% 
## 21.6545

Según este método, todas las observaciones por debajo de 12.87925 y por encima de 21.6545 se considerarán valores atípicos potenciales.

6.0.2 Extraer filas

A continuación, los números de fila de las observaciones fuera del intervalo pueden extraerse con la función which():

out_ind_perc <- which(Age < low_perc | Age > up_perc)
out_ind_perc
##  [1]  19  30  32  37  55  81  90 109 141 150 151 165 213 233 242 309 331 367 376
## [20] 380 383 416 462 478 484 485 493 503 507 564 580 601 637 653 676 731 750 784
## [39] 788 793

6.0.3 Imprimir valores

A continuación, se pueden imprimir los valores de la edad:

dat[out_ind_perc, "Age"]
Age
24.91
21.85
21.78
27.88
21.82
21.74
21.89
21.87
29.85
21.75
21.84
21.71
21.89
21.73
21.80
12.04
21.83
21.72
21.76
21.72
28.76
12.50
12.80
12.64
12.78
12.84
12.66
12.76
12.80
12.79
12.68
12.71
12.76
12.52
12.79
12.51
12.87
12.59
12.58
12.63

6.0.4 Imprimir todas las variables

Alternativamente, se pueden imprimir todas las variables de estos valores atípicos:

dat[out_ind_perc, ]
Gender Like Age Smoke Height Weight BMI School
Male TV 24.91 No 1.65 90 33.05785 Private
Female Network 21.85 Yes 1.53 59 25.20398 Public
Male Network 21.78 Yes 1.65 59 21.67126 Public
Female Network 27.88 Yes 1.63 55 20.70082 Private
Female Network 21.82 Yes 1.62 82 31.24524 Private
Male TV 21.74 No 1.88 80 22.63468 Private
Male TV 21.89 No 1.64 87 32.34682 Public
Male TV 21.87 Yes 1.80 50 15.43210 Private
Female TV 29.85 No 1.65 88 32.32323 Private
Male Network 21.75 Yes 1.69 80 28.01022 Public
Female Network 21.84 No 1.58 75 30.04326 Private
Female Network 21.71 No 1.72 86 29.06977 Private
Male Network 21.89 Yes 1.81 74 22.58783 Private
Male Network 21.73 Yes 1.62 54 20.57613 Private
Female Network 21.80 Yes 1.71 80 27.35885 Public
Male Network 12.04 Yes 1.60 50 19.53125 Private
Male TV 21.83 No 1.82 80 24.15167 Private
Male TV 21.72 No 1.78 75 23.67125 Private
Male Network 21.76 No 1.87 84 24.02128 Public
Female Network 21.72 Yes 1.50 59 26.22222 Public
Male Network 28.76 Yes 1.65 54 19.83471 Private
Male TV 12.50 Yes 1.76 72 23.24380 Private
Female TV 12.80 Yes 1.78 65 20.51509 Private
Female TV 12.64 No 1.62 56 21.33821 Public
Female Network 12.78 No 1.70 55 19.03114 Public
Female Network 12.84 No 1.64 51 18.96193 Private
Male Network 12.66 No 1.64 92 34.20583 Private
Male Network 12.76 Yes 1.80 77 23.76543 Public
Male Network 12.80 No 1.66 71 25.76571 Private
Male Network 12.79 No 1.79 73 22.78331 Private
Female Network 12.68 No 1.66 83 30.12048 Public
Female Network 12.71 No 1.72 100 33.80206 Public
Male TV 12.76 No 1.68 56 19.84127 Public
Male TV 12.52 No 1.75 82 26.77551 Public
Male Network 12.79 Yes 1.76 71 22.92097 Public
Male Network 12.51 Yes 1.62 59 22.48133 Private
Female Network 12.87 Yes 1.67 59 21.15529 Private
Female TV 12.59 Yes 1.62 75 28.57796 Private
Male Network 12.58 Yes 1.77 74 23.62029 Public
Male Network 12.63 Yes 1.75 51 16.65306 Private

Hay 40 valores atípicos potenciales según el método de los percentiles.

6.0.5 Ampliar intervalo

Para reducir este número, puede establecer los percentiles en 0.5% y 99.5%:

low_perc <- quantile(Age, 0.005, na.rm=TRUE)
up_perc <- quantile(Age, 0.995, na.rm=TRUE)

out_ind_perc <- which(Age < low_perc | Age > up_perc)

dat[out_ind_perc, ]
Gender Like Age Smoke Height Weight BMI School
Male TV 24.91 No 1.65 90 33.05785 Private
Female Network 27.88 Yes 1.63 55 20.70082 Private
Female TV 29.85 No 1.65 88 32.32323 Private
Male Network 12.04 Yes 1.60 50 19.53125 Private
Male Network 28.76 Yes 1.65 54 19.83471 Private
Male TV 12.50 Yes 1.76 72 23.24380 Private
Male TV 12.52 No 1.75 82 26.77551 Public
Male Network 12.51 Yes 1.62 59 22.48133 Private

Si se fijan los percentiles en 0.5% y 99.5%, además de los valores atípicos potenciales obtenidos con el criterio QR, se obtienen otros.

7 Cuarto método: Puntajes Z

Si sus datos proceden de una distribución normal, puede utilizar las puntuaciones \(z\), lo que puede hacerse con la función scale() de R. Según este método, cualquier puntuación \(z\) inferior a -2 o superior a 2 se considera rara inferior a -3 o superior a 3 se considera extremadamente rara.

Otros también utilizan una puntuación z inferior a -3.29 o superior a 3.29 para detectar valores atípicos. Este valor de 3.29 proviene del hecho de que 1 observación de cada 1000 está fuera de este intervalo si los datos siguen una distribución normal.

7.0.1 Estandarizar

En nuestro caso,

dat$Z_age <- scale(Age)
Z_age <-dat$Z_age

7.0.2 Histogramas

hist(Z_age, col = "blue")

library(ggplot2)

ggplot(dat) +
  aes(x = Z_age) +
  geom_histogram(bins = 30L, color = "red", fill = "#0c4c8a") +
  
  theme_minimal()

7.0.3 Resumen de 5 números

summary(Z_age)
##        V1          
##  Min.   :-2.21441  
##  1st Qu.:-0.60608  
##  Median : 0.06339  
##  Mean   : 0.00000  
##  3rd Qu.: 0.67757  
##  Max.   : 4.94669  
##  NA's   :2

Vemos que hay algunas observaciones por encima de 3.29, pero ninguna por debajo de -3.29.

7.0.4 Extraer filas

Identificar la fila en el conjunto de datos de estas observaciones:

which(Z_age < -3.29 | Z_age > 3.29)
## [1]  37 141 383

Vemos que las observaciones 37, 141 y 383 pueden considerarse valores atípicos según este método.

8 Quinto método: Filtro de Hampel

Otro método, conocido como filtro de Hampel, consiste en considerar como valores atípicos los valores situados fuera del intervalo formado por la mediana, más o menos 3 desviaciones absolutas de la mediana.

8.0.1 Hallar el intervalo

Para este método fijamos primero los límites del intervalo gracias a las funciones median() y mad():

low_hampel <- median(Age, na.rm=TRUE) - 3 * mad(Age, constant = 1, na.rm=TRUE)
low_hampel
## [1] 12.89
up_hampel <- median(Age, na.rm=TRUE) + 3 * mad(Age, constant = 1, na.rm=TRUE)
up_hampel
## [1] 22.52

Según este método, todas las observaciones inferiores a 12.89 y superiores a 22.52 se considerarán valores atípicos potenciales.

8.0.2 Extraer filas

A continuación, los números de fila de las observaciones fuera del intervalo pueden extraerse con la función which():

out_ind_hampel <- which(Age < low_hampel | Age > up_hampel)
out_ind_hampel
##  [1]  19  37 141 309 383 416 462 478 484 485 493 503 507 520 564 580 601 637 653
## [20] 676 731 750 784 788 793

De acuerdo al filtro de Hampel, hay 25 valores atípicos para la variable Age.

9 Pruebas estadísticas para detectar outliers

En esta sección, se presentarán 3 técnicas más formales para detectar valores atípicos:

  • Prueba de Grubbs.

  • Prueba de Dixon.

  • Prueba de Rosner.

Estas 3 pruebas estadísticas forman parte de técnicas más formales de detección de valores atípicos, ya que todas implican el cálculo de un estadístico de prueba que se compara con valores críticos tabulados (que se basan en el tamaño de la muestra y el nivel de confianza deseado).

Debe tenerse en cuenta que las 3 pruebas sólo son adecuadas cuando los datos (sin valores atípicos) tienen una distribución aproximadamente normal. Por lo tanto, debe verificarse el supuesto de normalidad antes de aplicar estas pruebas de valores atípicos (consulte cómo probar el supuesto de normalidad en R).

10 Prueba de Grubbs

10.0.1 Hipótesis

La prueba de Grubbs permite detectar si el valor más alto o más bajo de un conjunto de datos es un valor atípico. Las hipótesis nula y alternativa son las siguientes:

  1. Si queremos comprobar el valor más alto:

    • Hipótesis nula: El valor más alto no es un valor atípico.

    • Hipótesis alternativa: El valor más alto es un valor atípico.

  2. Si queremos probar el valor más bajo:

    • Hipótesis nula: El valor más bajo no es un valor atípico.

    • Hipótesis alternativa: El valor más bajo es un valor atípico.

Como en cualquier prueba estadística, si el valor p es inferior al umbral de significación elegido (generalmente \(\alpha\) = 0.05), se rechaza la hipótesis nula y se concluye que el valor más bajo/más alto es un valor atípico.

Por el contrario, si el valor p es mayor o igual que el nivel de significación, no se rechaza la hipótesis nula y concluiremos que, basándonos en los datos, no rechazamos la hipótesis de que el valor más bajo/más alto no es un valor atípico.

Debe tener en cuenta que la prueba de Grubbs no es adecuada para muestras de 6 o menos (n≤6).

10.0.2 Ejemplo (valor más alto)

Para realizar la prueba de Grubbs en R, utilizamos la función grubbs.test() del paquete outliers:

#install.packages("outliers")
#library(outliers)

test <- grubbs.test(Age)
test
## 
##  Grubbs test for one outlier
## 
## data:  Age
## G = 4.94669, U = 0.96926, p-value = 0.0002488
## alternative hypothesis: highest value 29.85 is an outlier

El valor p es 0.0002488. Al nivel de significación del 5%, rechazamos la hipótesis de que el valor 29.85 más alto es un valor atípico.

Por defecto, la prueba se realiza en el valor más alto (como se muestra en la última línea de la salida de R).

max(dat$Age)
## [1] NA

10.0.3 Ejemplo (valor más bajo)

Si desea realizar la prueba para el valor más bajo, simplemente se añade el argumento opposite = TRUE en la función grubbs.test():

test <- grubbs.test(Age, opposite = TRUE)
test
## 
##  Grubbs test for one outlier
## 
## data:  Age
## G = 2.21441, U = 0.99384, p-value = 1
## alternative hypothesis: lowest value 12.04 is an outlier

La salida de R indica que la prueba se realiza ahora sobre el valor más bajo (véase la hipótesis alternativa: el valor más bajo 12.04 es un valor atípico).

El valor p es 1. Al nivel de significación del 5%, no rechazamos la hipótesis de que el valor más bajo 12.04 no sea un valor atípico.

11 Prueba de Dixon

De forma similar a la prueba de Grubbs, la prueba de Dixon se utiliza para comprobar si un único valor bajo o alto es un valor atípico. Por lo tanto, si se sospecha que hay más de un valor atípico, la prueba debe realizarse individualmente para cada uno de ellos.

Tenga en cuenta que la prueba de Dixon es más útil para muestras pequeñas (normalmente \(n \leq 25\)).

11.0.1 Ejemplo

Para realizar la prueba de Dixon en R, utilizamos la función dixon.test() del paquete outliers. Sin embargo, restringimos nuestro conjunto de datos a las 30 primeras observaciones, ya que la prueba de Dixon sólo puede realizarse en muestras de pequeño tamaño (R arrojará un error y sólo acepta conjuntos de datos de 3 a 30 observaciones):

subdat <- dat[1:30, ]
test <- dixon.test(subdat$Age)
test
## 
##  Dixon test for outliers
## 
## data:  subdat$Age
## Q = 0.38443, p-value = 0.08647
## alternative hypothesis: highest value 24.91 is an outlier

Los resultados muestran que el valor más alto, 24.91, no es un valor atípico (valor p >0.05).

Para comprobar el valor más bajo, basta con añadir el argumento opposite = TRUE a la función dixon.test():

test <- dixon.test(subdat$Age,  opposite = TRUE)
test
## 
##  Dixon test for outliers
## 
## data:  subdat$Age
## Q = 0.072824, p-value = 0.2327
## alternative hypothesis: lowest value 16.02 is an outlier

Los resultados muestran que el valor más bajo, 16.02, no es un valor atípico (valor p >0.05).

Es una buena práctica comprobar siempre los resultados de la prueba estadística de valores atípicos con el diagrama de caja para asegurarse de que hemos comprobado todos los valores atípicos potenciales:

out_dixon <- boxplot.stats(subdat$Age)$out
boxplot(subdat$Age,col = "blue",
  ylab = "Age"
)
mtext(paste("Outliers: ", paste(out_dixon, collapse = ", ")))

A partir del diagrama de caja, podríamos aplicar la prueba de Dixon sobre el segundo valor menor no atípico, quitando el menor valor (en este caso, no sucederá nada porqu eno hay valore atípicos). Esto se puede hacer encontrando el número de fila del valor mínimo, excluyendo este número de fila del conjunto de datos y, por último, aplicando la prueba de Dixon a este nuevo conjunto de datos:

# find and exclude lowest value
remove_ind <- which.min(subdat$Age)
subsubdat <- subdat[-remove_ind, ]

# Dixon test on dataset without the minimum
test <- dixon.test(subsubdat$Age)
test
## 
##  Dixon test for outliers
## 
## data:  subsubdat$Age
## Q = 0.3942, p-value = 0.07922
## alternative hypothesis: highest value 24.91 is an outlier

12 Prueba de Rosner

12.0.1 Descripción

La prueba de Rosner para detectar valores atípicos tiene las ventajas de que:

1. Se utiliza para detectar varios valores atípicos a la vez (a diferencia de la prueba de Grubbs y Dixon, que debe realizarse de forma iterativa para detectar múltiples valores atípicos).

2. Está diseñada para evitar el problema del enmascaramiento, en el que un valor atípico cercano a otro valor atípico puede pasar desapercibido. 

A diferencia de la prueba de Dixon, la prueba de Rosner es más adecuada cuando el tamaño de la muestra es grande (\(n \geq 20\)). Por lo tanto, volvemos a utilizar el conjunto de datos inicial dat, que incluye todas las observaciones.

12.0.2 Ejemplo

Para realizar la prueba de Rosner utilizamos la función rosnerTest() del paquete EnvStats. Esta función requiere al menos 2 argumentos: los datos y el número de presuntos valores atípicos \(k\) (con \(k = 3\) como número predeterminado de presuntos valores atípicos).

Para este ejemplo, fijamos el número de presuntos valores atípicos en \(4\), tal y como sugiere el número de posibles valores atípicos esbozados en el diagrama de caja al principio del documento.

#install.packages("EnvStats")
#library(EnvStats)

test <- rosnerTest(dat$Age,  k = 4)
test
## 
## Results of Outlier Test
## -------------------------
## 
## Test Method:                     Rosner's Test for Outliers
## 
## Hypothesized Distribution:       Normal
## 
## Data:                            dat$Age
## 
## Number NA/NaN/Inf's Removed:     2
## 
## Sample Size:                     798
## 
## Test Statistics:                 R.1 = 4.946687
##                                  R.2 = 4.582779
##                                  R.3 = 4.283665
##                                  R.4 = 3.095325
## 
## Test Statistic Parameter:        k = 4
## 
## Alternative Hypothesis:          Up to 4 observations are not
##                                  from the same Distribution.
## 
## Type I Error:                    5%
## 
## Number of Outliers Detected:     3
## 
##   i   Mean.i     SD.i Value Obs.Num    R.i+1 lambda.i+1 Outlier
## 1 0 17.54734 2.487050 29.85     141 4.946687   3.983760    TRUE
## 2 1 17.53191 2.450062 28.76     383 4.582779   3.983444    TRUE
## 3 2 17.51780 2.419003 27.88      37 4.283665   3.983128    TRUE
## 4 3 17.50477 2.392393 24.91      19 3.095325   3.982811   FALSE

Los resultados interesantes se ofrecen en la tabla $all.stats:

test$all.stats
i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
0 17.54734 2.487050 29.85 141 4.946687 3.983760 TRUE
1 17.53191 2.450062 28.76 383 4.582779 3.983444 TRUE
2 17.51780 2.419003 27.88 37 4.283665 3.983128 TRUE
3 17.50477 2.392393 24.91 19 3.095325 3.982811 FALSE

Basándonos en la prueba de Rosner, vemos que sólo hay 3 valores atípicos porque sale TRUE en la última columna Outlier de la tabla. En este caso, se tratan de las observaciones 37, 383 y 141 (véase Obs.Num) con valores de 27.88, 28.76 y 29.85 (véase Value), respectivamente.

13 Detección de outliers con el algoritmo Local Outlier Factor (LOF)

El algoritmo Local Outlier Factor (LOF) es un método no supervisado de detección de anomalías que calcula la desviación de la densidad local de un punto de datos dado con respecto a sus vecinos. Considera como valores atípicos las muestras que tienen una densidad sustancialmente inferior a la de sus vecinos.

Las técnicas de detección de valores atípicos basadas en la proximidad se dividen en dos categorías principales:

  • Detección de valores atípicos basada en la densidad.

  • Detección de valores atípicos basada en la distancia.

En general, en la técnica de detección de valores atípicos basada en la proximidad, se considera que un objeto es un valor atípico si está alejado de la mayoría de los demás puntos.

Este enfoque es más general y sencillo que los enfoques estadísticos, ya que es más fácil determinar una medida de proximidad significativa para un conjunto de datos que determinar su distribución estadística.

En esta sección nos centraremos únicamente en la técnica de detección de valores atípicos basada en la densidad. La forma más sencilla de medir si un objeto está alejado de la mayoría de los demás puntos del conjunto de datos es utilizar la distancia al \(k\)-próximo más cercano o el LOF (Local Outlier Factor).

El método LOF se basa en puntuar los valores atípicos en función de la densidad en el vecindario. Esta técnica se basa en un parámetro conocido como puntuación de valores atípicos (outlier score). La puntuación de un objeto atípico es el recíproco de la densidad en el vecindario del objeto (la densidad es la distancia media a los vecinos más cercanos).

En la técnica LOF, la densidad local de un punto se compara con la de sus vecinos. Si la primera es significativamente menor que la segunda, es decir, si LOF es mayor que uno, el punto se encuentra en una región más dispersa que sus vecinos, lo que sugiere que se trata de un valor atípico.

La única limitación de LOF es que sólo funciona con datos numéricos.

14 Detección de valores atípicos basada en la densidad.

En R, en el paquete DMwR hay una función lofactor() que calcula los factores atípicos locales utilizando el algoritmo LOF.

#remotes::install_github("cran/DMwR")
library(DMwR2)

15 Ejemplo: Pasos

15.0.1 Paso 1: Descripción de los datos

Los datos se recogieron aplicando una encuesta a una muestra de estudiantes universitarios.

datosCompleto <- lsm::survey
attach(datosCompleto)

Es un data frame con 800 observaciones y 66 variables:

names(datosCompleto)
##  [1] "Observation"  "ID"           "Gender"       "Like"         "Age"         
##  [6] "Smoke"        "Height"       "Weight"       "BMI"          "School"      
## [11] "SES"          "Enrollment"   "Score"        "MotherHeight" "MotherAge"   
## [16] "MotherCHD"    "FatherHeight" "FatherAge"    "FatherCHD"    "Status"      
## [21] "SemAcum"      "Exam1"        "Exam2"        "Exam3"        "Exam4"       
## [26] "ExamAcum"     "Definitive"   "Expense"      "Income"       "Gas"         
## [31] "Course"       "Law"          "Economic"     "Race"         "Region"      
## [36] "EMO1"         "EMO2"         "EMO3"         "EMO4"         "EMO5"        
## [41] "GOAL1"        "GOAL2"        "GOAL3"        "Pre_STAT1"    "Pre_STAT2"   
## [46] "Pre_STAT3"    "Pre_STAT4"    "Post_STAT1"   "Post_STAT2"   "Post_STAT3"  
## [51] "Post_STAT4"   "Pre_IDARE1"   "Pre_IDARE2"   "Pre_IDARE3"   "Pre_IDARE4"  
## [56] "Pre_IDARE5"   "Post_IDARE1"  "Post_IDARE2"  "Post_IDARE3"  "Post_IDARE4" 
## [61] "Post_IDARE5"  "PSICO1"       "PSICO2"       "PSICO3"       "PSICO4"      
## [66] "PSICO5"

15.0.2 Paso 2: Solo variables numéricas

Con estos datos, trataremos de identificar los valores atípicos en el conjunto de datos mencionado utilizando el algoritmo LOF. Para ello, necesitamos obtener algunos datos numéricos de este conjunto de datos:

# get numeric columns using dplyr() function            
dat <- select_if(datosCompleto, is.numeric)
names(dat)
##  [1] "Observation" "Age"         "Height"      "Weight"      "BMI"        
##  [6] "Score"       "MotherAge"   "MotherCHD"   "FatherAge"   "FatherCHD"  
## [11] "SemAcum"     "Exam1"       "Exam2"       "Exam3"       "Exam4"      
## [16] "ExamAcum"    "Definitive"  "Expense"     "Income"      "Gas"        
## [21] "EMO1"        "EMO2"        "EMO3"        "EMO4"        "EMO5"       
## [26] "Pre_STAT1"   "Pre_STAT2"   "Pre_STAT3"   "Pre_STAT4"   "Post_STAT1" 
## [31] "Post_STAT2"  "Post_STAT3"  "Post_STAT4"
#dat_num <-dat[,c(2,3,6,12,19)]
dat_num <- na.omit(dat[,c(2,3,6,12,19)])
attach(dat_num)
names(dat_num)
## [1] "Age"    "Height" "Score"  "Exam1"  "Income"

15.0.3 Paso 3: Obtener puntuaciones de los outliers

Ahora obtendremos la puntuación de los valores atípicos con \(k= 7\) (se puede “jugar” cambiando este número).

##   [1] 1.4026230 1.0619596 1.0316504 1.0056654 0.9953993 0.9823177 0.9898877
##   [8] 0.9918855 0.9984843 1.0061247 1.0590509 1.0248310 1.0275860 0.9665033
##  [15] 0.9787895 0.9793029 1.0071739 1.1118235 2.3878823 0.9834475 0.9925646
##  [22] 0.9898602 0.9944061 1.0829753 1.0321800 1.0606849 1.0303762 1.0059530
##  [29] 1.1654133 1.0167858 1.2924968 1.1548130 1.1020300 1.0212932 1.0242093
##  [36] 0.9705743 2.9104686 1.1376481 1.0495141 0.9944060 1.1087530 1.0128771
##  [43] 1.0635620 1.0050146 0.9982726 0.9473382 0.9960751 1.0015551 1.0087514
##  [50] 1.0223266 1.0101924 1.0133967 1.0234448 1.0333744 1.0918950 1.0198649
##  [57] 0.9994641 1.0049608 0.9980829 1.0983885 1.0955723 0.9809427 1.0222187
##  [64] 0.9765732 1.0072988 1.0868215 0.9478462 1.0318391 0.9666088 1.1416123
##  [71] 1.0088030 1.1048294 1.1846529 0.9649793 0.9913576 1.0386493 0.9989650
##  [78] 1.0821781 1.0061429 1.0616892 1.1727934 1.0173856 0.9811507 1.0217221
##  [85] 1.0002308 1.0642125 1.0065970 1.0767250 0.9684638 1.2464851 1.0179074
##  [92] 0.9686664 1.2903373 1.0646654 0.9838721 1.0099556 1.0638540 1.1505956
##  [99] 0.9516724 1.0150176 1.2577339 1.0794116 1.0081777 0.9594014 1.0288116
## [106] 1.0066864 1.0052537 0.9991451 1.0414449 0.9908985 0.9980186 1.1461109
## [113] 1.0077373 1.1325761 0.9633165 0.9816842 1.2591742 1.0055665 1.1847754
## [120] 1.0215987 0.9857177 0.9832192 1.0477870 1.1296951 1.0508046 1.0162942
## [127] 0.9851260 0.9764242 0.9800485 0.9948392 1.0179174 1.0432785 0.9513276
## [134] 0.9653916 0.9856247 1.2911322 0.9527877 0.9777723 1.0954625 1.0253957
## [141] 3.8512180 1.0172217 1.0235467 0.9890704 1.0270199 1.0499001 0.9892276
## [148] 1.0370951 1.0075576 1.0941093 0.9958176 0.9957885 1.0180032 0.9868883
## [155] 0.9804026 0.9781390 1.0299175 1.1983281 0.9680299 0.9586617 1.0860450
## [162] 1.0093496 1.0459585 1.0347848 1.4630536 1.0710260 1.0020347 0.9889634
## [169] 1.2178421 1.1534945 0.9593807 1.0955034 0.9354596 1.0148837 1.0140448
## [176] 1.0779627 1.2721217 0.9889741 1.0008796 0.9720254 1.0497547 0.9851066
## [183] 1.1569688 1.0061985 0.9864084 0.9961062 1.0086997 1.0045567 1.0669498
## [190] 1.1552061 1.0688751 0.9648927 1.0696422 1.1159710 0.9925560 1.1208508
## [197] 0.9485097 1.0523715 1.0533085 1.0863404 0.9633985 1.1528576 1.0332994
## [204] 0.9666771 1.0849465 1.0046256 1.0600730 1.0077441 1.0016680 0.9657894
## [211] 1.1142667 1.0101283 1.2157554 0.9997833 1.0158917 0.9836085 1.0147705
## [218] 0.9770646 1.0619206 1.0534748 1.0107139 0.9954589 1.2185043 1.0263619
## [225] 1.0402427 1.1293837 0.9883427 1.1097477 1.0723298 1.0365153 1.0108074
## [232] 1.1429447 1.1567431 1.0044618 1.0000381 0.9755145 0.9814793 0.9888630
## [239] 0.9779175 1.2252034 0.9726094 1.4221783 1.3179644 1.0006366 1.2079902
## [246] 1.1502429 0.9863692 0.9983116 1.0483158 1.1648788 0.9978443 0.9787310
## [253] 1.0353671 0.9974131 1.0409729 0.9890875 1.0100892 1.0118005 1.0367602
## [260] 1.0651623 0.9845056 1.1778566 1.0367300 1.0175075 1.0658369 1.0416235
## [267] 0.9493710 1.0226488 1.0440164 1.0421078 1.0040911 1.0342798 1.0459064
## [274] 1.0030143 0.9955931 0.9659278 1.0456524 1.1974954 0.9470577 1.1170641
## [281] 1.0248774 0.9912545 1.0752818 1.0248011 0.9640223 1.1287609 1.0011066
## [288] 1.1729367 0.9376976 1.0048093 0.9957369 1.0618855 1.2537667 0.9924252
## [295] 1.0953991 1.0026622 1.0320831 1.0109453 0.9962359 1.0384624 0.9907687
## [302] 1.0160522 0.9413869 1.0028396 0.9992171 1.0273497 1.1920514 0.9953429
## [309] 1.3349608 1.0244356 1.0012517 1.0470195 1.0545229 1.0293404 1.0025591
## [316] 0.9700601 1.0093291 1.0017025 1.0953383 1.0251374 1.1438950 0.9882199
## [323] 1.2445794 1.1962482 1.0174794 0.9971341 0.9892574 1.3908174 0.9902291
## [330] 0.9546039 1.0661800 1.0071211 0.9836296 1.0080651 0.9710849 1.0461167
## [337] 1.0106497 0.9501875 1.0108688 1.0257266 1.0916877 0.9768981 0.9966830
## [344] 0.9522847 0.9680673 0.9700874 1.0058954 0.9790320 0.9817682 0.9556836
## [351] 0.9544986 1.0354461 0.9843651 1.0948079 1.0345736 0.9577759 1.0365673
## [358] 1.0109472 0.9977611 1.0635773 1.0660916 1.0266231 0.9964029 0.9715991
## [365] 0.9994907 1.0829627 1.0049583 0.9989715 0.9863707 1.0012103 0.9543856
## [372] 0.9818725 0.9929811 1.0261677 0.9768110 1.0487521 0.9772802 0.9993587
## [379] 1.0213422 1.0207513 1.0057383 0.9816345 3.3382646 1.0243640 1.0172329
## [386] 1.0044354 1.0163987 1.0258365 1.0051209 1.0241427 1.0018646 0.9903671
## [393] 1.0317103 0.9550695 1.0145954 1.1703997 1.0081685 1.1425166 1.0323980
## [400] 0.9881991 0.9690609 1.1407888 0.9930251 1.1192735 0.9480838 1.0153014
## [407] 1.0435463 1.0312993 0.9692083 1.1802180 1.0490959 1.0391855 0.9946505
## [414] 1.0184282 1.0318696 1.1660042 1.0801900 1.1370402 1.0141774 1.0201376
## [421] 0.9914951 1.0389611 1.0015919 0.9534384 1.0215780 1.0444365 0.9890530
## [428] 1.0587447 1.0845374 0.9605421 1.0153465 1.2227086 0.9776239 0.9993794
## [435] 1.0410165 0.9963123 1.4447991 1.0281165 0.9998328 0.9758324 0.9653247
## [442] 0.9850855 1.0406799 0.9722626 1.0668592 0.9924719 0.9470380 1.0427028
## [449] 0.9660365 1.0863503 1.0465290 1.0171202 1.0628123 1.0953044 0.9925704
## [456] 0.9812946 1.0047628 1.0034055 1.0028010 1.1164749 1.1119459 1.0468546
## [463] 1.0635434 1.0772076 1.0167472 1.0217359 0.9963084 1.0149292 1.1329096
## [470] 0.9984818 0.9797474 1.0941116 1.0169026 1.0072484 1.0110031 1.0011106
## [477] 1.0433650 1.1133612 0.9882243 1.0117282 1.0004027 1.0626346 1.1459655
## [484] 1.0015634 0.9880445 1.0128858 0.9948389 1.2498047 1.2869326 1.1399327
## [491] 1.0249878 1.0654323 1.2617938 1.0423947 1.0120343 1.0058536 1.0558582
## [498] 1.0011536 0.9878626 1.0904977 1.0595779 1.0497301 1.1409866 1.0084134
## [505] 1.0340165 0.9916131 1.0645925 1.1497868 0.9970446 1.0481412 1.0596220
## [512] 1.0252055 0.9701523 1.1678775 1.0858131 1.1019319 0.9875698 1.1804939
## [519] 1.1310272 1.1574534 1.0073103 1.0338155 1.0499535 1.0206629 0.9703335
## [526] 1.0941500 0.9917080 1.1310087 1.0321024 1.1103095 1.0862437 0.9761956
## [533] 1.0330583 1.0491563 1.2048782 1.0299143 1.1951320 1.0264469 1.2203593
## [540] 1.1133234 0.9675178 1.0206242 1.0677766 1.0858337 1.0271078 1.0128762
## [547] 1.0099020 1.0351955 1.0713099 1.0155020 1.3899521 1.0105374 1.0320481
## [554] 1.0001863 1.0586568 0.9649813 0.9813870 0.9834187 1.1117350 1.1117007
## [561] 1.0190378 0.9748324 0.9821826 1.1762409 1.0050723 0.9588067 1.0136077
## [568] 1.3985471 1.0079192 1.0755431 1.1284642 0.9856295 1.0413141 0.9917961
## [575] 0.9851828 1.1860542 1.0322817 1.0040960 0.9791677 1.1394441 1.0402248
## [582] 1.0003591 1.0303873 1.1931992 1.3608937 1.0411869 1.0157150 1.1729108
## [589] 1.2154448 0.9952440 1.3956017 1.2782088 0.9883668 1.0153890 0.9742676
## [596] 1.0028662 1.0388652 1.0264601 0.9885018 1.0698662 1.0524828 1.1117141
## [603] 0.9767319 1.0132716 1.0140089 1.3175474 0.9813986 1.0254096 0.9873907
## [610] 1.0511987 1.0686573 1.0135989 0.9634352 1.2525199 1.2017720 1.0276117
## [617] 1.0651185 1.1301634 0.9492676 0.9766296 1.0238985 1.1017031 1.0259446
## [624] 1.2430092 0.9616928 0.9684346 1.0223111 1.0451356 0.9878121 0.9588882
## [631] 1.2922454 1.0240104 1.0190668 0.9715186 1.0470281 1.0796316 1.0126342
## [638] 0.9907706 1.0651081 1.0972059 1.0207975 1.0242904 1.0856529 1.1706114
## [645] 1.0907976 1.1166518 1.0587905 0.9924200 1.0100030 1.0381987 1.0272740
## [652] 0.9992377 1.3299229 1.0864210 1.0066766 1.0979978 1.0810569 1.0717432
## [659] 1.1485254 1.0483646 1.3345620 0.9727599 1.0104054 0.9827025 1.0602388
## [666] 1.0978071 1.1232673 1.1269827 1.0213793 1.0763902 0.9922212 1.0780800
## [673] 1.0682818 1.2464630 1.0468552 1.0795465 0.9933231 1.0250768 1.0419155
## [680] 0.9869611 1.0485321 0.9583299 0.9608311 1.0017685 1.1129757 0.9967308
## [687] 1.0084346 1.2115309 0.9850309 0.9748513 0.9682318 1.3420435 0.9968575
## [694] 1.0417798 1.0763365 1.1527903 1.0248408 0.9558751 1.0182796 1.1027949
## [701] 1.0435491 1.0294341 0.9978981 1.0413287 1.0275325 1.0301633 1.0757710
## [708] 0.9492173 1.1555319 1.0306536 1.2113724 1.0373228 0.9850309 1.0106790
## [715] 0.9880916 0.9923417 0.9761060 1.0282128 1.0622007 1.0772350 1.0625492
## [722] 1.0637855 0.9882830 1.1639481 1.0429310 1.0082870 1.0930119 1.0551276
## [729] 1.1134884 0.9781440 1.4216746 1.1606871 1.0324760 1.0718101 1.0391602
## [736] 1.0051612 1.2544124 0.9892557 1.0831610 1.0850532 0.9919572 0.9693656
## [743] 1.2922139 1.0655693 1.0144074 0.9777445 1.0121160 1.0708887 1.0717932
## [750] 1.0331827 1.0242835 1.2723913 0.9490011 0.9753878 1.2935234 1.0113695
## [757] 1.0128266 1.0123082 1.1147694 0.9870937 1.1258679 1.0352350 0.9920637
## [764] 1.0101964 1.0288492 1.2479085 1.0067836 1.0334061 1.0680200 1.0193919
## [771] 1.0118896 1.0896854 1.0671322 0.9533642 1.0167539 1.1460145 1.0458404
## [778] 1.0805208 0.9865439 1.2724749 1.0261517 1.0434932 1.0220798 1.2883967
## [785] 0.9845553 1.0745388 0.9581787 1.0641679 1.2061298 1.0282701 1.0405894
## [792] 1.0486125 1.2818770 1.0578507

15.0.4 Paso 4: Obtener puntuaciones de los outliers

Ahora que se han calculado las puntuaciones de los valores atípicos, se puede trazar un gráfico de densidad como se muestra abajo:

15.0.5 Paso 5: Extraer fila de los outliers

A continuación, se obtienen las filas de los 7 valores atípicos que hay en los datos dat_num. Con esta información, se podrían identificar los valores atípicos correspondientes.

## [1] 141 383  37  19 165 437 242

15.0.6 Paso 6: Visualizar outliers (bidimensional)

Ahora podemos utilizar el gráfico de pares para visualizar los valores atípicos que están marcados con un signo “+” en rojo:

15.0.7 Paso 6: Visualizar outliers (tridimensional)

En el espacio se pueden visualizar algunos outliers.

#install.packages("rgl")
#library(rgl)
plot3d(Age, Height, Score, type="s", col=col)
#install.packages("rgl")
#library(rgl)
plot3d(Age, Exam1, Income, type="s", col=col)

16 Ejercicios

Como repaso personal, realizar algunos de los ejercicios que se encuentran en las siguientes notas de clase:

  1. Estadística y distribuciones de probabilidad: Hacer click derecho.

  2. Estadística inferencial: Hacer click derecho.

Bibliografía

Consultar el documento RPubs :: Análisis multivariado (bibliografía).

 

 
If you found any ERRORS or have SUGGESTIONS, please report them to my email. Thanks.