Descriptivos
0. Objetivo del práctico
El objetivo del práctico, es avanzar en el análisis de los datos a través del uso de estadísticos descriptivos. Para esto ya debemos contar con datos previamente procesados del práctico N°3. Recordemos en qué parte del proceso estamos

En este práctico veremos tanto la estimación puntual de estadísticos descriptivos, como su visualización para reportes, ya sea a través de tablas o de gráficos.
Recursos del práctico
En este práctico utilizamos los datos procesados CASEN 2020, que proviene de los datos originales de Encuesta de Caracterización Socioeconómica (CASEN).Recuerden siempre consultar el libro códigos antes de trabajar datos.
1. Paquetes a utilizar
Para este práctico utilizaremos principalmente, las librerías sjmisc y sjPlot.
sjmisc: esta paquete tiene múltiples funciones, desde la transformación de datos y variables. Este paquete suele complementar a  dplyr de tidyverse en sus funciones.
sjPlot: su principal función es la visualización de datos para estadística en ciencias sociales mediante tablas y gráficos.
Cargaremos los paquetes con pacman revisar práctico anterior
pacman::p_load(sjmisc,
               sjPlot,
               tidyverse,
               magrittr)
theme_set(theme_sjplot2())
2. Importar datos
Una vez cargado los paquetes a utilizar, debemos pasar al segundo paso: cargar los datos. Como indicamos al inicio, seguiremos utilizando los datos *CASEN que fue procesada en el práctico anterior, pero le añadimos una variable.
load("output/data/datos_proc.RData")
3. Explorar datos
Pero ¿cómo sabremos cuales son las variables que componen la base de datos procesada?, para ello usaremos dos códigos para conocer la base procesada que usaremos:
el código names, nos entrega los nombres de las variables que componen el data set
names(datos_proc)
## [1] "sexo"              "edad_tramo"        "ocupacion"        
## [4] "horas_mens"        "ingreso_percapita" "ife"
Mientras que la función head nos entrega el nombre y las primeras 10 filas que la componen.
head(datos_proc)
## # A tibble: 6 x 6
##         sexo edad_tramo ocupacion horas_mens ingreso_percapita       ife
##    <dbl+lbl> <chr>      <fct>          <dbl>             <dbl> <dbl+lbl>
## 1 2 [Mujer]  Joven      No                NA           195416.    1 [Sí]
## 2 1 [Hombre] Adulto     Sí               180           315861     2 [No]
## 3 2 [Mujer]  Joven      No                NA           315861     2 [No]
## 4 1 [Hombre] Adulto     Sí                45          1001389     2 [No]
## 5 1 [Hombre] Joven      No                NA          1001389     2 [No]
## 6 2 [Mujer]  Adulto     No                NA          1001389     2 [No]
Gracias a estos códigos sabemos que tenemos una aproximación de las variables que podríamos utilizar. Por el práctico anterior sabemos que podemos explorar nuestros datos con sjPlot::view_df()
| ID | Name | Label | Values | Value Labels | 
|---|---|---|---|---|
| 1 | sexo | Sexo | 1 2 | Hombre Mujer | 
| 2 | edad_tramo | <output omitted> | ||
| 3 | ocupacion | o1. La semana pasada, ¿trabajó al menos una hora? | Sà No | |
| 4 | horas_mens | y2_hrs. Número de horas mensuales pactadas con empleador | range: 1-720 | |
| 5 | ingreso_percapita | Ingreso total del hogar | range: 0.0-225200000.0 | |
| 6 | ife | y26d_hog. Últimos 12 meses, ¿alguien recibió Ingreso Familiar de Emergencia? | 1 2 9 | Sà No No sabe | 
4. Descripción de variables
Una vez conocidas las variables que incluye nuestros datos procesados, ¿cómo podemos realizar un análisis descriptivo para algún informe o reporte? Veamos algunas de las más comunes
4.1. Medidas de tendencia central
Para conocer las medidas de tendencia central de las variables hay dos opciones. En la primera se puede pedir el estadístico manualmente, en la segunda se puede pedir una tabla resumen.
Media
Para conocer la media de una variable se utiliza la función mean(), su estructura es:
mean(datos$variable, na.rm=TRUE)
El argumento na.rm=TRUE excluye del cálculo a los casos perdidos. Esto aplicado a nuestra variable ingreso_percapita se ve así:
mean(datos_proc$ingreso_percapita, na.rm=TRUE)
## [1] 355472.1
Media recortada
Pero, ¿qué pasa si la variable ingreso_percapita esta influenciada por casos influyentes? Para eso puedo pedir la media recortada agregando el argumento trim para excluir al 5% de cada extremo
mean(datos_proc$ingreso_percapita, na.rm=TRUE, trim = 0.025)
## [1] 305707.9
Aquí podemos ver que el valor es distinto.
Ya conocimos el promedio de la variable ingreso_percapita podemos informar cuanto es el promedio del ingreso en el hogar en Chile, pero antes de eso queremos saber ¿cuánto gana el 50% de los hogares? Para eso calcularemos la mediana
Mediana
Para el cálculo de la mediana se utiliza el comando median, su estructura es similar a la mean():
median(datos$variable, na.rm =TRUE)
median(datos_proc$ingreso_percapita, na.rm =TRUE)
## [1] 229184.5
Ahora ya sabemos que al menos un 50% de las familias en Chile tienen por ingreso $229.184.
Ya tenemos los estadísticos principales, pero ¿cómo los reportamos? ¿tenemos que sacar el promedio de cada variable una por una? ¡No!, para ello sjmisc tiene diferentes funciones, que veremos a continuación
Un resumen
Podemos obtener un resumen de todos estadísticos a partir de la función summary(). El argumento puede ser tanto una columna en particular como ingreso_percapita
summary(datos_proc$ingreso_percapita)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
##         0    138612    229184    355472    390890 225200000
También podemos hacerlo con todos los datos. Sólo que no tendrá mucho sentido para las variables nominales.
summary(datos_proc)
##       sexo        edad_tramo        ocupacion    horas_mens    
##  Min.   :1.000   Length:144418      Sí:60479   Min.   :  1.0   
##  1st Qu.:1.000   Class :character   No:83939   1st Qu.:146.0   
##  Median :2.000   Mode  :character              Median :180.0   
##  Mean   :1.547                                 Mean   :152.8   
##  3rd Qu.:2.000                                 3rd Qu.:180.0   
##  Max.   :2.000                                 Max.   :720.0   
##                                                NA's   :111080  
##  ingreso_percapita        ife       
##  Min.   :        0   Min.   :1.000  
##  1st Qu.:   138612   1st Qu.:1.000  
##  Median :   229184   Median :2.000  
##  Mean   :   355472   Mean   :1.766  
##  3rd Qu.:   390890   3rd Qu.:2.000  
##  Max.   :225200000   Max.   :9.000  
## 
summary() es una función muy potente, dado que no solo permite resúmenes de data.frames (datos), sino que también de otros objetos en R (como los modelos).
Ahora bien tiene limitantes para interactuar con dplyr y generar archivos de salida. Por ello ocuparemos descr de sjmisc
sjmisc::descr(datos_proc$ingreso_percapita,
        show = "all",
        out = "viewer",
        encoding = "UTF-8",
        file = "output/figures/tabla-ingreso.doc")
## 
## ## Basic descriptive statistics
## 
##  var    type                   label      n NA.prc     mean       sd   se
##   dd numeric Ingreso total del hogar 144418      0 355472.2 834151.2 2195
##        md  trimmed                   range      iqr   skew
##  229184.5 266168.1 225200000 (0-225200000) 252277.6 152.42
De más variables
datos_proc %>%
select(ingreso_percapita,  horas_mens) %>% 
sjmisc::descr(
  show = "all",
  out = "viewer",
  encoding = "UTF-8",
  file = "output/figures/tabla1.doc")
## 
## ## Basic descriptive statistics
## 
##                var    type
##  ingreso_percapita numeric
##         horas_mens numeric
##                                                     label      n NA.prc
##                                   Ingreso total del hogar 144418   0.00
##  y2_hrs. Número de horas mensuales pactadas con empleador  33338  76.92
##       mean        sd     se       md   trimmed                   range      iqr
##  355472.15 834151.23 2195.0 229184.5 266168.13 225200000 (0-225200000) 252277.6
##     152.83     54.69    0.3    180.0    159.83             719 (1-720)     34.0
##    skew
##  152.42
##   -0.98
Aquí podemos ver la variable var, el tipo de variable type, su etiqueta label, los casos válidos n, los casos perdidos NA.prc, las medidas de tendencia central y las de dispersión. sjmisc tiene muchos beneficios, ya que cómo interactúa con el mundo tidyverse es fácil de complementar con funciones como select de dplyr. Además con la función file se puede exportar automáticamente la tabla para los reportes.
4.3. Frecuencias
Frecuencias absolutas
Para conocer las frecuencias absolutas de una variable se podría usar la función table, esta nos arroja la frecuencia por cada categoría de respuesta
table(datos_proc$sexo) 
## 
##     1     2 
## 65474 78944
También podríamos usar la función flat_table, esta puede agrupar más variables y agruparlas.
flat_table(datos_proc, sexo, ocupacion, ife)
##                  ife    Sí    No No sabe
## sexo   ocupacion                        
## Hombre Sí             9695 23979     473
##        No            11263 19571     493
## Mujer  Sí             7527 18488     317
##        No            20084 31701     827
El problema es ¿cómo podríamos reportarla en nuestros informes? Si queremos una tabla general usaremos la función frq. Esta función devuelve una tabla de frecuencias de vectores etiquetados, como marco de datos.
sjmisc::frq(datos_proc$sexo,
        out = "viewer",
         title = "Frecuencias",
        encoding = "UTF-8",
         file = "output/figures/tabla2.doc") 
| val | label | frq | raw.prc | valid.prc | cum.prc | |
|---|---|---|---|---|---|---|
| 1 | Hombre | 65474 | 45.34 | 45.34 | 45.34 | |
| 2 | Mujer | 78944 | 54.66 | 54.66 | 100.00 | |
| NA | NA | 0 | 0.00 | NA | NA | |
| total N=144418 · valid N=144418 · x̄=1.55 · σ=0.50 | ||||||
5. Visualización
Ahora que ya sabemos como tener todos los estadísticos necesarios para escribir nuestros reportes, viene el segundo paso visualizar los estadísticos. Esto lo haremos con sjPlot
Para visualizar las frecuencias usaremos la función plot_frq, su estructura es la siguiente:
plot_frq(datos,  #base
  ...,          #variable
  title = "",   # título
  type = c("bar", "dot", "histogram", "line", "density", "boxplot", "violin") #tipo de gráfico
Para los gráficos, tenemos los siguientes códigos
5.1. Gráfico de barras de frecuencias simple
Si quisiéramos presentar gráficos que entreguen la frecuencia de cada categoría de respuesta, podemos presentarla de la siguiente forma:
plot_frq(datos_proc, edad_tramo,
          title = "Gráfico de frecuencias, barras",
          type = c("bar"))

Además de la visualización es importante el guardar los datos que se producen y sjPlot tiene su propio código para hacerlo a través de la función save_plot(), su estructura es esta:
save_plot(last_plot()) #se deja el formato del archivo (.png, .jpg, .svg o .tif) y la ruta de la carpeta
Así guardaríamos el gráfico anterior
save_plot(last_plot("/output/img/tab.png"))
5.2. Gráfico de puntos
Si tenemos más categorías y queremos mejorar el reporte, podemos usar este código:
plot_frq(datos_proc, edad_tramo,
          title = "Gráfico de frecuencias, puntos",
          type = c("dot"))

También podemos cambiar el orden del eje x e y
plot_frq(datos_proc$edad_tramo, type = "dot", show.ci = TRUE, sort.frq = "desc",
  coord.flip = TRUE, expand.grid = TRUE, vjust = "bottom", hjust = "left", title = "Gráfico de frecuencias, puntos cambiado"
)

5.3 Histogramas
Otra función que podemos hacer es graficar histogramas, sin embargo, como ya hemos visto, la variable ingreso_percapita tiene casos muy altos que distorsionan la variable. Para solucionar esto, ocuparemos lo aprendido en el práctico anterior y filtraremos la variable sacando los ingresos mayores a $2.000.000, con la función filter de dplyr
datos_proc %>%  filter(ingreso_percapita <= 2000000) %>% 
plot_frq(., ingreso_percapita,
          title = "Histograma",
          type = c("histogram"))

5.4 Densidad
Ahora que vemos la distribución del histograma, ¿cómo podemos ver su densidad?, es muy simple, para ello haremos un gráfico de densidad con el siguiente código
datos_proc %>%  filter(ingreso_percapita <= 2000000) %>%
plot_frq(., ingreso_percapita,
          title = "Gráfico de densidad",
          type = c("density"))

5.5 Gráfico de cajas
Para graficar los estadísticos de una variable, podemos hacerlo a través de un gráfico de cajas, para ello usaremos este código:
datos_proc %>%  filter(ingreso_percapita <= 2000000) %>%
plot_frq(., ingreso_percapita,
          title = "Gráfico de caja",
          type = c("boxplot"))

5.6 Gráfico de violín
Finalmente, si queremos presentar gráficos de violín, usamos este código
datos_proc %>%  filter(ingreso_percapita <= 2000000) %>%
    plot_frq(., ingreso_percapita,
          title = "Gráfico de violín",
          type = c("violin"))

Como pueden ver, el único argumento que se modificaba era type = , es decir, para hacer diversos gráficos, sólo se debe especificar el tipo de gráfico que queremos.
5.7 Gráfico de nube de puntos
Ahora, si quisiéramos graficar la distribución de dos variables, podemos hacerlo con la función plot_scatter, esta muestra el diagrama de dispersión de dos variables.
datos_proc %>%
  filter(ingreso_percapita <= 2000000, horas_mens <= 600) %>%
   plot_scatter(., horas_mens, ingreso_percapita)

También es posible agregar una variable de ocupación al diagrama de dispersión.
datos_proc %>%  filter(ingreso_percapita <= 2000000, horas_mens <= 600) %>%
    plot_scatter(., horas_mens, ingreso_percapita, edad_tramo)

6. Visualización bivariada
Ahora que ya hemos graficado las frecuencias de las variables, vamos a graficar frecuencias agrupadas, para ello usaremos la función plot:grpfrq de sjPlot, su estructura es la siguiente
plot_grpfrq(
  var.cnt,
  var.grp,
  type = c("bar", "dot", "line", "boxplot", "violin")
6.1 Gráfico de barras
La primera opción que nos entrega este código son los gráficos de barra, para usarlo queremos saber cuantos hombres y mujeres trabajaron al menos una hora la semana pasada, para ello graficaremos la variable sexo y ocupacion
plot_grpfrq(datos_proc$sexo, datos_proc$ocupacion,
  type = c("bar"), title = "Gráfico de barras")

Podemos ver que no solo nos muestra la frecuencia absoluta, sino que también la relativa en porcentaje
Pero además podemos ver agregar una tercera categoría, que es el total de ambas categorías. Para este ejercicio conoceremos que tramo de edad trabajo la semana pasada.
Para este ejercicio usaremos la función plot_xtab, de la misma librería
plot_xtab(datos_proc$edad_tramo, datos_proc$ocupacion, title = "Gráfico de barras")

6.2 Gráfico de barras horizontales
Con la misma función podemos graficar mediante barras horizontales
plot_xtab(datos_proc$edad_tramo, datos_proc$ocupacion, margin = "row", 
          bar.pos = "stack",
          title = "Gráfico de barras horizontales",
         show.summary = TRUE, coord.flip = TRUE)

6.3 Gráfico de líneas
Otra opción que tiene esta función, es la creación de gráficos de líneas, para ello conoceremos la relación entre el tramo etario y el recibir el IFE
plot_grpfrq(datos_proc$edad_tramo, datos_proc$ife,
            title = "Gráfico de línea",
            type = c("line"))

También podemos ver la relación de el tramo etario y si trabajó la semana pasada
plot_grpfrq(datos_proc$edad_tramo, datos_proc$ocupacion, 
            title = "Gráfico de línea",
            type = "line")

6.4 Gráfico de cajas
Ahora si queremos conocer cómo interactúa las horas de trabajo con el tramo etario, podemos visualizarlo mediante un gráfico de cajas
plot_grpfrq(datos_proc$horas_mens, datos_proc$edad_tramo,
            title = "Gráfico de caja",
             type = c("boxplot"))

Además, se puede incorporar una tercera variable, en este caso lo haremos con la variable sexo
plot_grpfrq(datos_proc$horas_mens, datos_proc$edad_tramo, intr.var = datos_proc$sexo, 
            title = "Gráfico de cajas",
            type = "box")

Nuevamente, la función nos permite la creación de múltiples gráficos, sólo se debe cambiar el argumento type =
7. Tablas de contingencia
¡No podemos terminar sin saber cómo hacer tablas de frecuencias cruzadas!
Por suerte sjPlot tiene la función sjt.xtab, que nos entrega tablas de frecuencias cruzadas
sjt.xtab(datos_proc$sexo, datos_proc$ife,  title = "Tabla de contingencias",
         show.col.prc=TRUE,
         show.summary=FALSE)
| Sexo | y26d_hog. Últimos 12 meses, ¿alguien recibió Ingreso Familiar de Emergencia? | Total | ||
|---|---|---|---|---|
| SÃ | No | No sabe | ||
| Hombre | 20958 43.2 % | 43550 46.5 % | 966 45.8 % | 65474 45.3 % | 
| Mujer | 27611 56.8 % | 50189 53.5 % | 1144 54.2 % | 78944 54.7 % | 
| Total | 48569 100 % | 93739 100 % | 2110 100 % | 144418 100 % | 
¿Qué pasó? ¿por qué salen esos símbolos raros en la tabla?
¡Es por la codificación!, para ello le agregamos el argumento encoding = "UTF-8" y ya tenemos nuestra tabla de frecuencias cruzadas
sjt.xtab(datos_proc$sexo, datos_proc$ife,
         show.col.prc=TRUE,
         show.summary=FALSE, 
         encoding = "UTF-8", 
         title = "Tabla de contingencia",
         file = "output/figures/tabla3.doc")
| Sexo | y26d_hog. Últimos 12 meses, ¿alguien recibió Ingreso Familiar de Emergencia? | Total | ||
|---|---|---|---|---|
| SÃ | No | No sabe | ||
| Hombre | 20958 43.2 % | 43550 46.5 % | 966 45.8 % | 65474 45.3 % | 
| Mujer | 27611 56.8 % | 50189 53.5 % | 1144 54.2 % | 78944 54.7 % | 
| Total | 48569 100 % | 93739 100 % | 2110 100 % | 144418 100 % | 
8. Correlación
Ahora veremos estadísticos bivariados, como la correlación, en esta ocasión generaremos una tabla de correlación entre las variables horas_mens y ingreso_percapita, para eso usaremos la función tab_corr de sjPlot
Previamente debemos seleccionar las variables a utilizar, ya que no tiene sentido incluir en el análisis variables nominales
datos_proc %>%
select(ingreso_percapita, horas_mens) %>% 
tab_corr(.,
         triangle = "lower",   
         title = "Tabla de correlación",
         encoding = "UTF-8", 
         file = "output/figures/tabla4.doc")
| Ingreso total del hogar | y2_hrs. Número de horas mensuales pactadas con empleador | |
|---|---|---|
| Ingreso total del hogar | ||
| y2_hrs. Número de horas mensuales pactadas con empleador | 0.054*** | |
| Computed correlation used pearson-method with listwise-deletion. | ||
9. Anova
Finalmente, si queremos reportar un análisis de Anova, no podemos dejar de lado este gráfico que nos otorga la función sjp.aov1 del paquete sjPlot
sjp.aov1(datos_proc$ingreso_percapita, datos_proc$sexo, title = "Anova")

9. Resumen del práctico
¡Eso es todo por este práctico! Hoy aprendimos a:
- Manejar datos descriptivos en Rstudio
- A obtener tablas descriptivas
- A visualizar los descriptivos
- A obtener tablas de contingencia
- A obtener tablas de correlación
- A obtener gráficos de Anova
7. Reporte de progreso
¡Recuerda rellenar tu reporte de progreso. En tu correo electrónico está disponible el código mediante al cuál debes acceder para actualizar tu estado de avance del curso.