Proceso a seguir para explorar los datos:
Modelar o modelizar
Representación gráfica
Transformación de datos
Hay dos tipos de preguntas que siempre sirven para entender los datos:
¿Qué tipo de variaciones sufren las variables?
¿Qué tipo de covariación sufren las variables?
Terminos importantes a tener claro en el mundo de la estadística:
variable: cantidad, factor o propiedad medible
valor: estado de una variable al ser medida
observación: conjunto de medidas tomadas en condiciones similares.
datos tabulares: conjunto de valores, asociados a cada variable y observación se los datos estan limpios, cada variable tiene su propia celda, cada variabe tiene su columna y cada observación su fila.
Para poder ver esta variación, hay dos formas de verlo; a través de a distribución y a través de su visualización. Para tratar estos dos sistemas, depende de si es una variable categórica o numérica.
library(tidyverse)
## -- Attaching packages ----------------------------------------------------------------------------------------------- tidyverse 1.2.1 --
## v ggplot2 3.1.0 v purrr 0.2.5
## v tibble 1.4.2 v dplyr 0.7.8
## v tidyr 0.8.2 v stringr 1.3.1
## v readr 1.1.1 v forcats 0.3.0
## -- Conflicts -------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
ggplot(data = diamonds)+
geom_bar(mapping = aes(x = cut)) # usaremos barras para ver las variaciones
Si queremos contar los valores por barra, con una tibble, usaremos la función count():
diamonds %>%
count(cut) # conteo de los valores de la variable discreta
Podemos usar un histograma de frecuencias:
ggplot(data = diamonds) +
geom_histogram(mapping = aes(x = carat), binwidth = .5)
También podemos usar la función count() con coutwidth() para saber las frequancias en número:
diamonds %>%
count(cut_width(carat, .5)) # cut_width nos ayudaa a medir diferentes anchuas para trabajar mejor. Diferentes anchuras pueden mostrar diferentes patrones.
Para ver mas información, podemos hacerlo de la siguiente manera:
diamonds_filter <- diamonds %>%
filter(carat<3)
ggplot(data = diamonds_filter)+
geom_histogram(mapping = aes(x = carat), binwidth = .05)
Este gráfico nos muestra más información para visualizar y entendor los gráficos.
En algunas ocasiones querremos comparar diferentes histogramas en uno solo. En ese caso es mejor usar freqpoly (polígono de frecuencia), que en vez de usar las barras para sacar informaciín, usa polígonos. Ejemplo:
ggplot(data = diamonds_filter, mapping = aes(x = carat, color = cut))+
geom_freqpoly(binwidth = .1)
En este gráfico podemos ver la variación, y nos debe llevar a empezar a formular preguntas útiles. Para eso debes ser escéptico!
Viendo el anterioir gráfico, ¿qué preguntas nos deberíamos hacer?
¿Cuáles son los valores más comunes?¿Por qué?
¿Cuáles son los valores mas raros?¿Por qué?¿Cumple con nuestras expectativas?
Visualización de patrones: ¿Ves algun patrón característico o inusual?¿Podemos explicarlos?
En el dataset de diamantes podemos ver datos curioso como por ejemplo; Dado un valor muy alto, los valores decaen:
diamonds_filter <- diamonds %>%
filter(carat<3)
ggplot(data = diamonds_filter)+
geom_histogram(mapping = aes(x = carat), binwidth = .01)
¿Cuál podría ser el motivo? Deberíamos saber más sobre los diamentes y su proceso de creación.
El siguiente paso es agrupar valores similares para detectar subgrupos dentro de la ifnormación. Para detectarlos, se deben hacer 3 preguntas:
¿Qué determina que los elementos de un cluster sean similares entre ellos?
¿Qué determina que clusters separados sean diferentes entre si?
Describir y explicar cada uno de los clusters.
¿Por qué alguna observación puede ser calsificada en un cluster erroneo?
Un outlier es una observación que no encaja en ningún patrón, totalmente inusual. Lo normal es que sea un error en la entrada de datos, pero pueden no serlo y ser una información muy relevante. Ejemplo:
ggplot(data = diamonds)+
geom_histogram(mapping = aes(x = y), binwidth = .5)
¿Cómo podríamos hacer un zoom en estos outliers? Limitaremos el eje de ordenadas entre 0 y 100.
ggplot(data = diamonds)+
geom_histogram(mapping = aes(x = y), binwidth = .5)+
coord_cartesian(ylim = c(0,100))
Vamos a extraer los outliers para poder analizarlos:
unusual_diamonds <- diamonds %>%
filter(y<2 | y>30) %>%
select(price, x,y,z) %>%
arrange(y)
unusual_diamonds
Podemos ver que estos valores son muy atípicos, y podemos ver cuales tienen sentido o no.
Si tenen un efecto muy pequeño en la creación del modelo, lo mejor es sustituir los outliers por NA. Es preferible trabajar con un grupo de datos comunes, que no trabajar con datos que contengan outliers. Sin embargo, si aportan explicabilidad en los datos, es mejor incluirlos en el modelo.
Como debemos tratar los outliers? Tenemos varias opciones:
good_diamonds <- diamonds %>%
filter(between(y, 2.5, 29.5))
good_diamonds <- diamonds %>%
mutate(y = ifelse(y < 2 | y > 30, NA, y))
La función ggplot() no incluye los NAs, pero te advierte cuantos hay:
ggplot(data = good_diamonds, mapping = aes(x = x, y = y))+
geom_point() # podemos usar el parametro na.rm = T para eliminar el WARNING
## Warning: Removed 9 rows containing missing values (geom_point).
¿Cómo podemos entender porqué un valores atípico respecto los otros valores? Si nos vamos en el dataset de flights, podemos mirar si para los vuelos cancelados y no cancelados tene alguna relación con el horario de salida.
Para realizar este análisis crearemos una nueva vaariable que nos diga si es NA o no es NA.
nycflights13::flights %>%
mutate(
cancelled = is.na(dep_time),
sched_hour = sched_dep_time %/% 100, # para quedarme solo con la hora
sched_min = sched_dep_time %% 100,
sched_dep_time = sched_hour + sched_min/60
) %>%
ggplot(mapping = aes(sched_dep_time))+
geom_freqpoly(mapping = aes(color = cancelled), binwidth = 1/4) # que salgan cada 5 munitos
Podemos ver algunos patrones, por ejemplo que en las horas de máximos vuelos hay más vuelos cancelados.
EL concepto de covariación describe el comportamiento entre dos o más variabes para saber si cambian de forma conjunta. El tipo de gráfico depende del tipo de variables utilizadas.
Caso más simple -> categoría vs variable continua: gráfico con el geom_freqpoly()
ggplot(data = diamonds, mapping = aes(x = price))+
geom_freqpoly(mapping = aes(color = cut), binwidth = 500)
Pero cuando la comparación es complicada por que, por ejemplo, una categoría pesa mucho mas que otra, miraremos la densidad:
ggplot(data = diamonds, mapping = aes(x = price, y = ..density..))+
geom_freqpoly(mapping = aes(color = cut), binwidth = 500)
Este gráfico sí que nos permite comparar los resutados. Interesante ver que los diamantes estilo “fair”, tienen un precio más caro que los otros, pero estas hipótesisis pueden estar influenciadas por la poca información que nos puede dar el gráfico, es decir, puede que la categoría fer solo tenga 10 observaciones, y una de ellas tenga un precio mas elevado que las otras. Esta imagen nos haría creer que los diamantes fair se suelen vender más caros.
En los boxplots, el 50% de los valores caen dentro de la caja. Está dividido entre quartiles, caja y bigotes. La caja empieza en el 1Quartil (25% de los datos) y va hasta el 3 quartil, 75% de los datos. La distancia entre estos dos quartiles es el rango intercuartílico.
Dentro de la caja, se representa en una linea la mediana, el percentil 50% de la distribución. Nos ayuda a ver por ejemplo si la información es simétrica respecto de la media.
Outliers, datos que caen mas de 1.5 veces mas lejos del rango intercuartílico, de Q3 y de Q1. Son valores atípicos dentro de dicha distribución.
Los bigotes, se extienden desde la caja hasta el punto más cercano al rango intercuartílico por 1.5, que no sea considerado outlier.
¿Cómo usarlo dentro de la caja?
ggplot(data = diamonds, mapping = aes(x = cut, y = price))+
geom_boxplot()
Además el boxplot nos está mostrando como la categoría está ordenada, ya que vemos que va de fair a ideal, de peor a mejor.
¿Cómo podríamos ordenarlo nosotros mismos en otro caso?
ggplot(data = mpg, mapping = aes(x = class, hwy))+
geom_boxplot()
Para ordenarlos, usaríamos el siguiente código.
ggplot(data = mpg)+
geom_boxplot(mapping = aes(x = reorder(class, hwy, FUN = median),y = hwy))+
coord_flip()
En este caso lo hemos ordenado a partir de la mediana, de menor a mayor.
En este apartado veremos como podemos visualizar la correlación entre dos variables categóricas. Por eso miraremos cuantas variables categóricas caen en el mismo parta del “mapa”. Ejemplo:
ggplot(data = diamonds) +
geom_count(mapping = aes(x = cut, y = color))
Pero también se puede hacer un cálculo exacto con dplyr, ¿cómo?:
diamonds %>%
count(color, cut) # aquí podemos ver el tamaño de las bolas, mas claras que de forma visual
Podemos tambien hacerlo con unas estéticas sobre el count que habamos de hacer:
diamonds %>%
count(color, cut) %>%
ggplot(mapping = aes(x = cut, y = color)) +
geom_tile(mapping = aes(fill = n))
Se pueden usar también otros paquetes para ampliar nuestra capacidad de visualización 3d o más grandes:
d3heatmap
heatmaply
Esta parte nos permitirá analizar la correlación entre dos variables continuas:. Por ejemplo, ¿hay alguna relación entre precio y los kilates?
ggplot(data = diamonds)+
geom_point(mapping = aes(x = carat, y = price), alpha = .01)
También se pueden usar las bins para mapear la información en dos variables continuas. Usaremos dos funciones de ggplot(), necessitamos un nuevo paquete porque no vienen por defecto. Para isntalarlo library(hexbin):
geom_bin2d() -> crea divisiones rectangulares
geom_hex() -> divide el espacio en hexagonos.
Las dos funciones dividen el plano coordenado en cajas 2d, y luego utiliza un sistema de color para indicar cuantos punto caen dentro de la subdivisión.
library(hexbin)
ggplot(data = diamonds)+
geom_bin2d(mapping = aes(x = carat, y = price))
Aquí se muestran que el color es mayor contra más dimantes cean en cada rectángulo.
Y si queremos usar mapas hexagonales:
library(hexbin)
ggplot(data = diamonds)+
geom_hex(mapping = aes(x = carat, y = price))
Podemos también tratar una variable numérica con una variable categórica, para combinar la con otra variable continua. Ideal para hacer boxplots:
diamonds %>%
filter(carat<3) %>%
ggplot(mapping = aes(x = carat, y = price))+
geom_boxplot(mapping = aes(group = cut_width(carat, 0.1)))
Podemos añadir otro parámetro para aumentar la información que nos dan los boxplots del anterior gráfico, varwidth igual a TRUE. Es un modo de mostrar si la anchura de boxplot es proporcional al numero de puntos, contra más ancho, más puntos:
diamonds %>%
filter(carat < 3) %>%
ggplot(mapping = aes(x = carat, y = price))+
geom_boxplot(mapping = aes(group = cut_width(carat, 0.1)), varwidth = TRUE)
Podemos también hacer las divisiones pero que aproximadamente se lleven el mismo numero de puntos el dataset dentro de cada una de ellas, con el cut_number():
diamonds %>%
filter(carat < 3) %>%
ggplot(mapping = aes(x = carat, y = price))+
geom_boxplot(mapping = aes(group = cut_number(carat, 20))) # 20 cajas se llevan mas o menos el mismo numero de observaciones, para asi entender la dispersion de los datos
Si hay una relación sistemática entre dos variables podróa ser visible con un gráfico. Siempre que veamos un patrón hay preguntas a hacerse:
¿Es fruto de la coincidencia?
¿Cómo podemos describir las relaciones de dicho patrón?¿lineal, exponencial, logarítmica?¿qué forma?
¿Fuerza de la relación?
¿Hay otras variables afectadas?
¿Esta relación cambia si miramos a subgrupos o clusters dentro del dataset?
Por ejemplo, hagamos un scatter plot de los geisers del parque de yellowstone:
ggplot(data = faithful)+
geom_point(mapping = aes(x = eruptions, y = waiting))
Cuando dos variables tienen una variación conjunta o covariación elevada, se pueden usar los valores de una para predecir los de otra. Si la covariación es debido a una relación causal, que es un tipo de relación causal, se podría tomar los valores de una para predecir la otra.
Los modelos es una forma para extraer patrones de los datos. En el dataset de diamantes, podemos mirar la relación entre precio y kilates para buscar patrones. Vamos a crear un modelo para predecir el precio a partir de los kilates. Para eso cargaremos la librería “modelr” que nos permite crear modelos incluyendo el formato pipe.
library(modelr)
# Creacion de un modelo de regresion lineal
mod <- lm(log(price)~log(carat), data = diamonds)
mod
##
## Call:
## lm(formula = log(price) ~ log(carat), data = diamonds)
##
## Coefficients:
## (Intercept) log(carat)
## 8.449 1.676
Hagamos la predicción del precio con el modelo creado:
diamonds_pred <- diamonds %>%
add_residuals(mod) %>%
mutate(res = exp(resid))
head(diamonds_pred)
ggplot(data = diamonds_pred) +
geom_point(mapping = aes(x=carat, y = resid))