Un análisis sobre DatasauRus

DatasauRus

El objetivo de esta notebook es el de familiarizarnos con el uso de algunas técnicas estadísticas comunes y su uso (y su mis-use) en el análisis de datos.

En tal sentido, para la primera parte se utilizarán las librerías contenidas en el ecosistema de tidyverse, tales como dplyr para “arreglar” los datos o ggplot, para visualizarlos.

Configuraciones previas

Inicialmente,si es la primera vez que se usan, se deben instalar las librerías llamadas a continuación con la función install.packages():

install.packages("datasauRus")
install.packages("haven",dependencies = T)
install.packages("splitstackshape",dependencies = T)
library(tidyverse)
library(datasauRus)
library(haven)
library(splitstackshape)

Una vez instalada la librería, se puede llamar a las funciones que contiene de dos formas: tal como se ejecutó en la celda anterior, (utilizando la función library()) o, alternativamente, colocando el nombre de la librería seguido de un doble dos puntos ::, por ejemplo, dplyr::mutate(). En caso de que se elija la segunda opción no es necesario llamar a library, siempre y cuando se la tenga instalada en el equipo.

Es una buena práctica, especialmente cuando uno inicia, seguir el segundo método, aún cuando se llame a library() para que nuestro yo futuro recuerde de dónde sacó una determinada función.

Los datos

Todo análisis debe iniciarse cargando la materia prima del mismo: los datos. Ya sea desde un archivo plano (.csv, .txt,etc), desde diferentes instancias de base de datos relacionales (SQL Server, Oracle, etc.) o desde páginas de internet (urls, web scrapping, etc), el primer paso es lograr que R “lea” la información.

En este sentido, se utilizará una tabla de información contenida en la librería datasauRus:

data <- datasauRus::datasaurus_dozen

Como primer paso, se debe conocer el conjunto de datos.

head(data,10)
## # A tibble: 10 x 3
##    dataset     x     y
##    <chr>   <dbl> <dbl>
##  1 dino     55.4  97.2
##  2 dino     51.5  96.0
##  3 dino     46.2  94.5
##  4 dino     42.8  91.4
##  5 dino     40.8  88.3
##  6 dino     38.7  84.9
##  7 dino     35.6  79.9
##  8 dino     33.1  77.6
##  9 dino     29.0  74.5
## 10 dino     26.2  71.4

O, viendo el final:

tail(data)
## # A tibble: 6 x 3
##   dataset        x     y
##   <chr>      <dbl> <dbl>
## 1 wide_lines  34.7  19.6
## 2 wide_lines  33.7  26.1
## 3 wide_lines  75.6  37.1
## 4 wide_lines  40.6  89.1
## 5 wide_lines  39.1  96.5
## 6 wide_lines  34.6  89.6

Viendo la estructura del conjunto de datos:

dplyr::glimpse(data)
## Rows: 1,846
## Columns: 3
## $ dataset <chr> "dino", "dino", "dino", "dino", "dino", "dino", "dino", "dino"~
## $ x       <dbl> 55.3846, 51.5385, 46.1538, 42.8205, 40.7692, 38.7179, 35.6410,~
## $ y       <dbl> 97.1795, 96.0256, 94.4872, 91.4103, 88.3333, 84.8718, 79.8718,~

Como se puede observar, existen tres variables, $dataset$, una variable de texto o character y las variables $x$ e $y$, ambas numéricas.

Para entender la información, verificamos cuántas categorías existen en la variable $dataset$:

unique(data$dataset)
##  [1] "dino"       "away"       "h_lines"    "v_lines"    "x_shape"   
##  [6] "star"       "high_lines" "dots"       "circle"     "bullseye"  
## [11] "slant_up"   "slant_down" "wide_lines"

Como muestra, vamos a analizar $4$ variables tomadas al azar para realizar nuestro análisis de forma inicial:

set.seed(12)
unique(data$dataset)[runif(n = 4,min=1, max=length(unique(data$dataset)))]
## [1] "dino"       "bullseye"   "slant_down" "v_lines"

Dino

Inicialmente, vamos a realizar un subset de datos para quedarnos con dino.

Esto puede lograrse de varias formas, en este caso se ilustra con funciones de R base como con funciones obtenidas de dyplr:

dino <- data[data$dataset=="dino",]
head(dino,3)
## # A tibble: 3 x 3
##   dataset     x     y
##   <chr>   <dbl> <dbl>
## 1 dino     55.4  97.2
## 2 dino     51.5  96.0
## 3 dino     46.2  94.5

O, viendo el final:

tail(dino,3)
## # A tibble: 3 x 3
##   dataset     x     y
##   <chr>   <dbl> <dbl>
## 1 dino     50    95.8
## 2 dino     47.9  95  
## 3 dino     44.1  92.7

Utilizando dplyr:

dino_dyplr <- data %>%
filter(dataset=="dino") 

head(dino_dyplr)
## # A tibble: 6 x 3
##   dataset     x     y
##   <chr>   <dbl> <dbl>
## 1 dino     55.4  97.2
## 2 dino     51.5  96.0
## 3 dino     46.2  94.5
## 4 dino     42.8  91.4
## 5 dino     40.8  88.3
## 6 dino     38.7  84.9

La media

dino está compuesto por dos variables continuas. Para calcular sus medias ocupamos la función mean():

mean(dino$x)
## [1] 54.26327
mean(dino$y)
## [1] 47.83225

Podemos redondear usando la función round()

round(mean(dino$x),digits = 2)
## [1] 54.26
round(mean(dino$y),digits = 2)
## [1] 47.83

Varianza - Desviación estándar

La varianza la obtenemos utilizando la función var():

var(dino$x)
## [1] 281.07
var(dino$y)
## [1] 725.516

La desviación estándar, la raiz cuadrada de la varianza, mediante sd():

sd(dino$x)
## [1] 16.76514
sd(dino$y)
## [1] 26.9354

Covarianza y correlación

Como se vio, una medida del tipo de relación lineal entre dos variables es la covarianza, la cual puede calcularse utilizando la función cov():

cov(dino$x,dino$y)
## [1] -29.11393

De esto, se deriva que la relación es negativa, es decir, cuando $x$ está por encima de su promedio, $y$ suele estar por debajo del suyo.

Complementando, para tener una idea de la magnitud de la relación, se calcula la correlación utilizando cor():

cor(dino$x, dino$y)
## [1] -0.06447185

El cual sugiere una leve relación negativa.

Rango

Se suele calcular el rango, la diferencia entre el valor máximo y el valor mínimo de los datos, para enteder la dispersión entre los mismos:

El valor mínimo se lo obtiene mediante la función min():

min(dino$x)
## [1] 22.3077
min(dino$y)
## [1] 2.9487

El valor máximo, mediante max():

max(dino$x)
## [1] 98.2051
max(dino$y)
## [1] 99.4872

Una forma alternativa

Si tenemos una rutina preestablecida (repetitiva) no hay necesidad de realizar el análisis muchas veces, sino que es posible crear un loop y ‘automatizar’ el análisis. Esto puede lograrse como se explica a continuación:

En primer lugar, obtenemos algunos datos sobre los cuales iterar (los mismos que íbamos a analizar anteriormente) y los añadimos al vector $prueba$:

set.seed(12)
prueba <- unique(data$dataset)[runif(n = 4,min=1, max=length(unique(data$dataset)))]
prueba
## [1] "dino"       "bullseye"   "slant_down" "v_lines"

Los loops en R tienen la siguiente estructura:

## for(iterador in lista){
## 
## hacer algo 
## 
## }

Por ejemplo:

for(i in c("a","c","d")){
    print(i)
}
## [1] "a"
## [1] "c"
## [1] "d"

Ahora, verificando los nombres de las columnas:

colnames(data)
## [1] "dataset" "x"       "y"

Verificando los valures únicos de la columna dataset:

unique(data$dataset)
##  [1] "dino"       "away"       "h_lines"    "v_lines"    "x_shape"   
##  [6] "star"       "high_lines" "dots"       "circle"     "bullseye"  
## [11] "slant_up"   "slant_down" "wide_lines"
for(i in unique(data$dataset)){
    print(paste("Dataset",i,sep=" "))
    datos <- data[data$dataset==paste(i),]
    cat(paste("Media x:", round(mean(datos$x),2),sep=" "),"\n")
    cat(paste("Media y:", round(mean(datos$y),2),sep=" "),"\n")
    cat(paste("Varianza x:", round(var(datos$x),2)),"\n")
    cat(paste("Varianza y:", round(var(datos$y),2)),"\n")
    cat(paste("Desv. Estd. x:", round(sd(datos$x),2)),"\n")
    cat(paste("Desv. Estd. y:", round(sd(datos$y),2)),"\n")
    cat(paste("Covarianza:", round(cov(datos$x,datos$y),2)),"\n")
    cat(paste("Correlación:", round(cor(datos$x,datos$y),2)),"\n")
    cat("\n")
}
## [1] "Dataset dino"
## Media x: 54.26 
## Media y: 47.83 
## Varianza x: 281.07 
## Varianza y: 725.52 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -29.11 
## Correlación: -0.06 
## 
## [1] "Dataset away"
## Media x: 54.27 
## Media y: 47.83 
## Varianza x: 281.23 
## Varianza y: 725.75 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -28.97 
## Correlación: -0.06 
## 
## [1] "Dataset h_lines"
## Media x: 54.26 
## Media y: 47.83 
## Varianza x: 281.1 
## Varianza y: 725.76 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -27.87 
## Correlación: -0.06 
## 
## [1] "Dataset v_lines"
## Media x: 54.27 
## Media y: 47.84 
## Varianza x: 281.23 
## Varianza y: 725.64 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -31.37 
## Correlación: -0.07 
## 
## [1] "Dataset x_shape"
## Media x: 54.26 
## Media y: 47.84 
## Varianza x: 281.23 
## Varianza y: 725.22 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.93 
## Covarianza: -29.62 
## Correlación: -0.07 
## 
## [1] "Dataset star"
## Media x: 54.27 
## Media y: 47.84 
## Varianza x: 281.2 
## Varianza y: 725.24 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.93 
## Covarianza: -28.43 
## Correlación: -0.06 
## 
## [1] "Dataset high_lines"
## Media x: 54.27 
## Media y: 47.84 
## Varianza x: 281.12 
## Varianza y: 725.76 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -30.94 
## Correlación: -0.07 
## 
## [1] "Dataset dots"
## Media x: 54.26 
## Media y: 47.84 
## Varianza x: 281.16 
## Varianza y: 725.24 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.93 
## Covarianza: -27.25 
## Correlación: -0.06 
## 
## [1] "Dataset circle"
## Media x: 54.27 
## Media y: 47.84 
## Varianza x: 280.9 
## Varianza y: 725.23 
## Desv. Estd. x: 16.76 
## Desv. Estd. y: 26.93 
## Covarianza: -30.85 
## Correlación: -0.07 
## 
## [1] "Dataset bullseye"
## Media x: 54.27 
## Media y: 47.83 
## Varianza x: 281.21 
## Varianza y: 725.53 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -30.98 
## Correlación: -0.07 
## 
## [1] "Dataset slant_up"
## Media x: 54.27 
## Media y: 47.83 
## Varianza x: 281.19 
## Varianza y: 725.69 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -30.99 
## Correlación: -0.07 
## 
## [1] "Dataset slant_down"
## Media x: 54.27 
## Media y: 47.84 
## Varianza x: 281.12 
## Varianza y: 725.55 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -31.15 
## Correlación: -0.07 
## 
## [1] "Dataset wide_lines"
## Media x: 54.27 
## Media y: 47.83 
## Varianza x: 281.23 
## Varianza y: 725.65 
## Desv. Estd. x: 16.77 
## Desv. Estd. y: 26.94 
## Covarianza: -30.08 
## Correlación: -0.07

Como se observa, los loops también pueden volverse complicados, aún más si hubiésemos tenido que almacenar los resultados en alguna estructura compacta.

Se debe notar, sin embargo, algo sorprendente: aún cuando los $datasets$ son distintos, los principales estadísticos son iguales.

Otra alternativa: the “tidy way”

Una forma más sencilla de obtener los mismos resultados, hubiese sido aprovechando algunas funciones diseñadas para esto. Así, dplyr contiene algunas funciones importantes:

data_sum = data %>% 
    group_by(dataset) %>% 
    summarize(
        media_x    = round(mean(x),2),
        media_y    = round(mean(y),2),
        var_x = round(var(x),2),
        var_y = round(var(y),2),
        esv_est_x = round(sd(x),2),
        desv_est_y = round(sd(y),2),
        cov_x_y = round(cov(x,y),2),
        corr_x_y  = round(cor(x, y),2)
    )

Visualizando los resultados:

head(data_sum)
## # A tibble: 6 x 9
##   dataset  media_x media_y var_x var_y esv_est_x desv_est_y cov_x_y corr_x_y
##   <chr>      <dbl>   <dbl> <dbl> <dbl>     <dbl>      <dbl>   <dbl>    <dbl>
## 1 away        54.3    47.8  281.  726.      16.8       26.9   -29.0    -0.06
## 2 bullseye    54.3    47.8  281.  726.      16.8       26.9   -31.0    -0.07
## 3 circle      54.3    47.8  281.  725.      16.8       26.9   -30.8    -0.07
## 4 dino        54.3    47.8  281.  726.      16.8       26.9   -29.1    -0.06
## 5 dots        54.3    47.8  281.  725.      16.8       26.9   -27.2    -0.06
## 6 h_lines     54.3    47.8  281.  726.      16.8       26.9   -27.9    -0.06

Si observamos, el resultado es un tibble (algo muy parecido a un dataframe), el cual pudo haberse asignado a un nuevo objeto.

Por otra parte, queda una duda, ¿son todos estos $dataset$ iguales? Para quitarnos la duda, vamos a graficarlos utilizando ggplot():

Análisis Gráfico

¿Qué sucede si graficamos?

data %>%
filter(dataset %in% c("dino","circle","star"))%>%
ggplot(aes(x=x, y=y, colour=dataset))+
    geom_point()+
    theme_minimal()+
    theme(legend.position = "none")+
    facet_wrap(~dataset, ncol=3)

DataSaurus

Como es evidente, los diferentes $dataset$ son distinto, sin embargo, producen los mismos resultados… ¿por qué?

Conclusión

Una imagen vale más que mil palabras. La importancia de “dibujar” los datos antes de realizar cualquier análisis numérico.

Siguiente