```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

# Datos faltantes

Los procesos experimentales son complejos, lo que hace que en ocasiones haya pérdida de datos. Esta pérdida es natural, lo que implica que debemos saber qué hacer en caso de estar presente. En R, los datos faltantes aparecen como `NA`, y pueden ocurrir en variables de cualquier naturaleza, como numéricas:

```{r echo = T}
x <- c(1, 4, 6, 2, 8, NA, 10)
x
```

o categóricas:

```{r echo = T}
a <- c("a", "c", "r", NA, "s", NA, "q")
a
```

Los valores faltantes afectan las operaciones que realizamos con las variables en que están presentes, como la suma de sus elementos:

```{r echo = T}
sum(x)
```

el promedio ó desviación estándar:

```{r echo = T}
mean(x)
sd(x)
```

Es natural entonces que existan estrategias para identificar los datos faltantes y manejarlos de modo que nos permitan hacer los cálculos que necesitamos. La primera estrategia es su omisión en los cálculos, lo cual está implementado en la mayoría de las funciones nativas de R como un argumento extra `na.rm = TRUE`. Por ejemplo para calcular la suma de elementos:

```{r echo = T}
sum(x, na.rm = T)
```

El valor por defecto de `na.rm = FALSE`, porque no debería haber `NA`s, y de este modo se pueden detectar sin previa exploración. Es buena práctica, sin embargo, revisar las bases de datos para encontrarlos y estar conscientes de que es necesario hacer algo al respecto.

## Detección de valores faltantes

Como es usual, es posible hacer esta exploración manualmente, sin embargo, esto no funciona cuando tenemos bases de datos grandes. En este caso R nos puede ayudar a encontrarlos. La primera función que debemos conocer es `is.na`, la cual genera un objeto lógico, indicando si un valor es `NA` (`TRUE`) o no (`FALSE`). En el caso de los objetos `x` y `a`:

```{r echo = T}
is.na(x)
is.na(a)
```

Si tenemos un vector grande, inspeccionar a mano cuáles posiciones tienen valores faltantes puede consumir mucho tiempo, pero esto lo podemos hacer con dos funciones, `table` y `which`. Por un lado `table` nos indicará cuántos `NA` hay en la base o variable que estemos inspeccionando:

```{r echo = T}
table(is.na(x))
```

mientras que `which` indicará la posición:

```{r echo = T}
which(is.na(x))
```

## Eliminación de valores

Una vez que tenemos identificada la presencia, cantidad y posición de los valores faltantes debemos tomar una serie de decisiones sobre qué haremos con esto valores faltantes. Como vimos al inicio, en algunas funciones podemos eliminar esas posiciones para hacer el cálculo con el argumento `na.rm` (remove NA). Existe una función llamada `na.omit` que podemos aplicar a priori a los objetos que tienen valores faltantes:

```{r echo = T}
na.omit(x)
na.omit(a)
```

Como es de esperarse, eliminar los valores no soluciona ningún problema de fondo, pues solamente estamos ignorándolos, es entonces que es pertinente preguntarnos si es posible reemplazarlos por algún valor.

## Reemplazo de datos faltantes por valores

Este procedimiento es riesgoso, porque en realidad no conocemos el valor real, a menos que haya una razón logística por la cual esos datos no están. Podría tratarse por ejemplo de que los datos que faltan sean 0, debido a que no nos tomamos la molestia de capturarlos en ese caso. Por otra parte, podría tratarse de errores de medición, y por lo tanto cambiar los `NA` por 0's no es un procedimiento aceptable. Necesitamos decidir si los valores que vamos a reemplazar tienen sentido y que afecten lo menos posible el resto del análisis y las conclusiones. 
Una alternativa es por ejemplo asignarle a esos valores el promedio de esa variable en cada nivel de tratamiento o bloque experimental. 

Para reemplazar con 0's el procedimiento sería el siguiente:

```{r echo = T}
x[is.na(x)] <- 0 
x
```

Y para reemplazar con el valor promedio:

```{r echo = T}
x <- c(1, 4, 6, 2, 8, NA, 10) #Debemos volver a generar el objeto porque ya reemplazamos el NA con 0

x[is.na(x)] <- mean(x, na.rm = T)
```

# Datos atípicos

Los datos atípicos son aquellos cuyos valores son mucho más grandes o pequeños que el resto. Estos pueden ocurrir por alguna de las siguientes razones:

- Muestras contaminadas
- Muestras de poblaciones diferentes
- Muestras obtenidas de manera incorrecta
- Alta variación natural en respuesta a un tratamiento
- Error de análisis
- Error de captura

Existen métodos estadísticos para detectar datos atípicos (outliers), basados en el supuestos de que las mediciones erróneas serán sustancialmente diferentes del resto, utilizando medidas de ubicación y dispersión.

Para identificar los datos atípicos podemos comenzar con ver un resumen de los cuartiles. Trabajaremos con una variable extraída de la base `mpg` similar a `mtcars`, pero extraída del paquete `ggplot2`:

```{r echo = T}
datos <- ggplot2::mpg
summary(datos$hwy)
```

y explorar el rango (mínimo y máximo) de valores en que ocurren los datos:

```{r echo = T}
range(datos$hwy)
```

Aún cuando esta información es útil no sabemos aún cuántos datos ocurren con los valores identificados de 12.0 y 44.0, para lo cual un histograma y boxplot son útiles:

```{r echo=T, fig.height=4, fig.width=6, fig.align='center', message = F, warning = F}
library(ggplot2)

ggplot(datos, aes(x = hwy)) + geom_histogram()
```

```{r echo=T, fig.height=4, fig.width=3}
ggplot(datos, aes(y = hwy)) + geom_boxplot()
```

En ambos gráficos podemos ver que entre los datos de los percentiles superiores en efecto hay dos o tres valores que parecieran atípicos. En los datos de los percentiles podría haber uno, que no aparece en el boxplot. La técnica que se utiliza en la implementación de R de boxplot, para decidir cuándo un valor es atípico es el rango intercuartil (IQR):

$$I = [q_{0.25} + 1.5 \times IQR; q_{0.75} + 1.5 \times IQR ]$$

donde $IQR = q_{0.75} - q_{0.25}$, y $q$ es el cuantil que se indica con el subíndice. Estos valores podemos extraerlos con la funcion `boxplot` de `graphics`:

```{r echo = T}
atipicos <- boxplot.stats(datos$hwy)$out
atipicos
```

Y utilizando estos valores podemos identificar las unidades obsercavionales *sospechosas*:

```{r}
id.atip <- which(datos$hwy %in% atipicos)

knitr::kable(datos[id.atip, ])
```

Estos procedimientos adolecen de lo mismo que los análisis exploratorios, no son *objetivos* y carecen de formalidad. Las siguientes pruebas estadísticas están diseñadas para identificar datos atípicos de la manera más robusta posible:

- Grubbs
- Dixon
- Rubner

y todas están implementadas en el paquete `outliers`. Estas pruebas estadísticas buscan deseachar por medio de probabilidad, la hipótesis nula ($H_0$) de que "No hay datos atípicos". Veamos un ejemplo para valores en la parte izquiera de la curva de distribución:

```{r echo = T}
outliers::grubbs.test(datos$hwy, opposite = FALSE)
```

En el resultado de la prueba de Grubbs debemos fijarnos en el valor estimado de *P*, si este es $P > 0.05$, aceptamos $H_0$. Por lo tanto inferimos que el valor del dato 44 no es atípico. La misma hipótesis pero para los valores más pequeños que la media la podemos probar cambiando el argumento `opposite`:

```{r echo = T}
outliers::grubbs.test(datos$hwy, opposite = TRUE)
```

Dado que $P \gg 0.05$ también podemos aceptar la hipótesis nula.

## ¿Qué hacer con los datos atípicos?

Hemos visto algunas técnicas para identificar datos atípicos, y en caso de estar presentes, debemos tomar decisiones sobre qué hacer con ellos. Lo primero que deberíamos hacer es identificar la razón por la cual esos datos son anómalos, lo que nos ayudará a tomar medidas correctivas. Por ejemplo, si las razones de su presencia es impericia de quien opera un equipo o falla del equipo, sería difícil encontrar un valor sensato para sustituir. Otra de las razones que no se listan arriba es el uso de escalas diferentes (°K en lugar de °C, p. ej.), lo que resulta fácil de corregir mediante las reglas de conversión.

[Codigo fuente de este tutorial](Faltantes-atipicos.Rmd)

[Regresar al índice del curso](index.html)