5  Estadística Descriptiva

Esta práctica contiene ejercicios que muestran cómo realizar un análisis descriptivo de un conjunto de datos mediante estadísticos muestrales, como por ejemplo:

5.1 Ejercicios Resueltos

Para la realización de esta práctica se requieren los siguientes paquetes:

library(tidyverse) 
# Incluye los siguientes paquetes:
# - readr: para la lectura de ficheros csv. 
# - dplyr: para el preprocesamiento y manipulación de datos.
library(vtable) # para resúmenes estadísticos.
library(skimr) # para resúmenes estadísticos.
library(summarytools) # para resúmenes estadísticos.
library(knitr) # para el formateo de tablas.

Ejercicio 5.1 En una encuesta a 25 matrimonios sobre el número de hijos que tenían se obtuvieron los siguientes datos:

1, 2, 4, 2, 2, 2, 3, 2, 1, 1, 0, 2, 2, 0, 2, 2, 1, 2, 2, 3, 1, 2, 2, 1, 2
  1. Crear un conjunto de datos con la variable hijos.

    df <- data.frame(hijos = c(1, 2, 4, 2, 2, 2, 3, 2, 1, 1, 0, 2, 2, 0, 2, 2, 1, 2, 2, 3, 1, 2, 2, 1, 2))
  2. Calcular el tamaño muestral.

    nrow(df)
    [1] 25
  3. Calcular la media.

    mean(df$hijos)
    [1] 1.76
  4. Calcular la mediana.

    median(df$hijos)
    [1] 2
  5. Calcular la moda.

    El paquete base de R no tiene implementada ninguna función para calcular la moda, así que definiremos nuestra propia función.

    moda <- function(x) {
    u <- unique(x) # Vector con los valores de la muestra sin repetir (sin ordenar).
    tab <- tabulate(match(x, u)) # Frecuencias absolutas de los valores en u.
    u[tab == max(tab)] # Valor con la mayor frecuencia.
    }
    
    moda(df$hijos)
    [1] 2
  6. Calcular el mínimo.

    min(df$hijos)
    [1] 0
  7. Calcular el máximo.

    max(df$hijos)
    [1] 4
  8. Calcular los cuartiles.

    quantile(df$hijos, prob=c(0.25, 0.5, 0.75))
    25% 50% 75% 
      1   2   2 
  9. Calcular los percentiles 5 y 95.

    quantile(df$hijos, prob=c(0.05, 0.95))
     5% 95% 
    0.2 3.0 
  10. Calcular el rango.

    max(df$hijos) - min(df$hijos)
    [1] 4
  11. Calcular el rango intercuartílico.

    IQR(df$hijos)
    [1] 1
  12. Calcular la varianza

    R dispone de la función var para calcular la cuasivarianza o varianza corregida (xix¯)2n1, pero no dispone de una función para calcular la varianza, de manera que para calcularla hay que corregir la cuasivarianza.

    n <- nrow(df)
    # Cuasivarianza
    print(paste("Cuasivarianza:", var(df$hijos)))
    [1] "Cuasivarianza: 0.773333333333333"
    # Varianza
    print(paste("Varianza: ", var(df$hijos)*(n-1)/n))
    [1] "Varianza:  0.7424"
  13. Calcular la desviación típica.

    R dispone de la función sd para calcular la cuasidesviación típica o desviación típica corregida (xix¯)2n1, pero no dispone de una función para calcular la desviación típica, de manera que para calcularla hay que corregir la cuasidesviación típica.

    n <- nrow(df)
    # Cuasidesviación típica
    print(paste("Cuasidesviación típica:", sd(df$hijos)))
    [1] "Cuasidesviación típica: 0.879393730551528"
    # Desviación típica
    print(paste("Desviación típica: ", sd(df$hijos)*sqrt((n-1)/n)))
    [1] "Desviación típica:  0.861626369141521"
  14. Calcular el coeficiente de variación.

    sd(df$hijos) / abs(mean(df$hijos))
    [1] 0.4996555
  15. Calcular el coeficiente de asimetría.

    Para calcular el coeficiente de asimetría se utiliza el paquete moments.

    [1] 0.1068549

    Como g1 está próxima a 0, la distribución es casi simétrica.

  16. Calcular el coeficiente de apuntamiento.

    Para calcular el coeficiente de apuntamiento se utiliza el paquete moments.

    kurtosis(df$hijos)
    [1] 3.71169

    Como g2>0, la distribución es más apuntada de lo normal (leptocúrtica). Como además g2(2,2) se puede concluir que la muestra es demasiado apuntada para provenir de una población normal.

Ejercicio 5.2 El fichero colesterol.csv contiene información de una muestra de pacientes donde se han medido la edad, el sexo, el peso, la altura y el nivel de colesterol, además de su nombre.

  1. Crear un data frame con los datos de todos los pacientes del estudio a partir del fichero colesterol.csv.

    df <- read.csv("https://aprendeconalf.es/estadistica-practicas-r/datos/colesterol.csv")
    head(df)
                            nombre edad sexo peso altura colesterol
    1 José Luis Martínez Izquierdo   18    H   85   1.79        182
    2               Rosa Díaz Díaz   32    M   65   1.73        232
    3        Javier García Sánchez   24    H   NA   1.81        191
    4          Carmen López Pinzón   35    M   65   1.70        200
    5         Marisa López Collado   46    M   51   1.58        148
    6            Antonio Ruiz Cruz   68    H   66   1.74        249
  2. Calcular el tamaño muestral según el sexo.

    Con la función table del paquete base de R.

    table(df$sexo)
    
    H M 
    8 6 

    Con la función count del paquete dplyr de tidyverse.

    library(dplyr)
    count(df, sexo)
      sexo n
    1    H 8
    2    M 6
  3. Calcular la media y la desviación típica del nivel de colesterol sin tener en cuenta los datos perdidos.

    # Media
    mean(df$colesterol, na.rm = TRUE)
    [1] 220.2308
    # Desviación típica:
    sd(df$colesterol, na.rm = TRUE)
    [1] 39.84795
  4. Realizar un resumen estadístico con la media, el mínimo, los cuartiles y el máximo.

    Con la función summary del paquete base de R.

        nombre               edad           sexo                peso       
     Length:14          Min.   :18.00   Length:14          Min.   : 51.00  
     Class :character   1st Qu.:24.75   Class :character   1st Qu.: 61.00  
     Mode  :character   Median :35.00   Mode  :character   Median : 65.00  
                        Mean   :38.21                      Mean   : 70.92  
                        3rd Qu.:49.75                      3rd Qu.: 78.00  
                        Max.   :68.00                      Max.   :109.00  
                                                           NA's   :1       
         altura        colesterol   
     Min.   :1.580   Min.   :148.0  
     1st Qu.:1.705   1st Qu.:194.0  
     Median :1.755   Median :210.0  
     Mean   :1.769   Mean   :220.2  
     3rd Qu.:1.840   3rd Qu.:249.0  
     Max.   :1.980   Max.   :280.0  
                     NA's   :1      

    Con la función st del paquete vtable.

    Summary Statistics
    Variable N Mean Std. Dev. Min Pctl. 25 Pctl. 75 Max
    edad 14 38 16 18 25 50 68
    sexo 14
    ... H 8 57%
    ... M 6 43%
    peso 13 71 16 51 61 78 109
    altura 14 1.8 0.12 1.6 1.7 1.8 2
    colesterol 13 220 40 148 194 249 280

    Con la función skim del paquete skimr.

    Data summary
    Name df
    Number of rows 14
    Number of columns 6
    _______________________
    Column type frequency:
    character 2
    numeric 4
    ________________________
    Group variables None

    Variable type: character

    skim_variable n_missing complete_rate min max empty n_unique whitespace
    nombre 0 1 14 31 0 14 0
    sexo 0 1 1 1 0 2 0

    Variable type: numeric

    skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
    edad 0 1.00 38.21 15.62 18.00 24.75 35.00 49.75 68.00 ▇▅▃▅▂
    peso 1 0.93 70.92 16.13 51.00 61.00 65.00 78.00 109.00 ▇▅▅▂▂
    altura 0 1.00 1.77 0.12 1.58 1.70 1.75 1.84 1.98 ▆▇▆▃▃
    colesterol 1 0.93 220.23 39.85 148.00 194.00 210.00 249.00 280.00 ▂▇▂▅▅

    Con las funciones descr y dfSummary del paquete summarytools.

    altura colesterol edad peso
    Mean 1.7685714 220.2307692 38.2142857 70.9230769
    Std.Dev 0.1150155 39.8479482 15.6213787 16.1269006
    Min 1.5800000 148.0000000 18.0000000 51.0000000
    Q1 1.7000000 194.0000000 24.0000000 61.0000000
    Median 1.7550000 210.0000000 35.0000000 65.0000000
    Q3 1.8500000 249.0000000 51.0000000 78.0000000
    Max 1.9800000 280.0000000 68.0000000 109.0000000
    MAD 0.1111950 41.5128000 17.7912000 14.8260000
    IQR 0.1350000 55.0000000 25.0000000 17.0000000
    CV 0.0650330 0.1809372 0.4087837 0.2273858
    Skewness 0.2052057 -0.0022401 0.3238511 0.9149779
    SE.Skewness 0.5973799 0.6163361 0.5973799 0.6163361
    Kurtosis -0.9852205 -1.2502343 -1.2886761 -0.1208155
    N.Valid 14.0000000 13.0000000 14.0000000 13.0000000
    Pct.Valid 100.0000000 92.8571429 100.0000000 92.8571429
    print(dfSummary(df, plain.ascii = FALSE, style = "grid"), method = "render")

    Data Frame Summary

    df

    Dimensions: 14 x 6
    Duplicates: 0
    No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
    1 nombre [character]
    1. Antonio Fernández Ocaña
    2. Antonio Ruiz Cruz
    3. Carmen López Pinzón
    4. Carolina Rubio Moreno
    5. Javier García Sánchez
    6. José Luis Martínez Izquie
    7. José María de la Guía San
    8. Macarena Álvarez Luna
    9. Marisa López Collado
    10. Miguel Angel Cuadrado Gut
    [ 4 others ]
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    1 ( 7.1% )
    4 ( 28.6% )
    14 (100.0%) 0 (0.0%)
    2 edad [integer]
    Mean (sd) : 38.2 (15.6)
    min ≤ med ≤ max:
    18 ≤ 35 ≤ 68
    IQR (CV) : 25 (0.4)
    12 distinct values 14 (100.0%) 0 (0.0%)
    3 sexo [character]
    1. H
    2. M
    8 ( 57.1% )
    6 ( 42.9% )
    14 (100.0%) 0 (0.0%)
    4 peso [numeric]
    Mean (sd) : 70.9 (16.1)
    min ≤ med ≤ max:
    51 ≤ 65 ≤ 109
    IQR (CV) : 17 (0.2)
    12 distinct values 13 (92.9%) 1 (7.1%)
    5 altura [numeric]
    Mean (sd) : 1.8 (0.1)
    min ≤ med ≤ max:
    1.6 ≤ 1.8 ≤ 2
    IQR (CV) : 0.1 (0.1)
    14 distinct values 14 (100.0%) 0 (0.0%)
    6 colesterol [numeric]
    Mean (sd) : 220.2 (39.8)
    min ≤ med ≤ max:
    148 ≤ 210 ≤ 280
    IQR (CV) : 55 (0.2)
    13 distinct values 13 (92.9%) 1 (7.1%)

    Generated by summarytools 1.0.1 (R version 4.4.2)
    2025-01-28

  5. ¿En qué variable es más representativa la media?

    Con la función (https://cran.r-project.org/web/packages/vtable/vignettes/sumtable.html) del paquete vtable.

    sumtable(df, summ = c('mean(x)', 'sd(x)', 'sd(x)/mean(x)'),
    summ.names = c("Media", "Desviación Típica", "Coef. Variación"))
    Warning in sumtable(df, summ = c("mean(x)", "sd(x)", "sd(x)/mean(x)"), summ.names = c("Media", : Factor variables ignore custom summ options. Cols 1 and 2 are count and percentage.
    Beware combining factors with a custom summ unless factor.numeric = TRUE.
    Summary Statistics
    Variable Media Desviación Típica Coef. Variación
    edad 38 16 0.41
    sexo 14
    ... H 8 57%
    ... M 6 43%
    peso 71 16 0.23
    altura 1.8 0.12 0.065
    colesterol 220 40 0.18

    Con las funciones summarise y across del paquete dplyr de tidyverse.

    library(tidyverse)
    summarise(df, across(.cols = where(is.numeric), .fns = list(Media = ~ mean(.x, na.rm = T), `Desviación Típica` = ~ sd(.x, na.rm = T), `Coef. Variación` = ~ sd(.x, na.rm=T) / mean(.x, na.rm=T)))) |>
    kable()
    edad_Media edad_Desviación Típica edad_Coef. Variación peso_Media peso_Desviación Típica peso_Coef. Variación altura_Media altura_Desviación Típica altura_Coef. Variación colesterol_Media colesterol_Desviación Típica colesterol_Coef. Variación
    38.21429 15.62138 0.4087837 70.92308 16.1269 0.2273858 1.768571 0.1150155 0.065033 220.2308 39.84795 0.1809372

    Pivotando el datra frame con pivot_longer y agrupando con group_by.

    library(tidyverse)
    df |> select(where(is.numeric)) |> 
        pivot_longer(everything(), names_to = "Variable", values_to = "Valor") |>
        group_by(Variable) |>
        summarise("Media" = mean(Valor, na.rm = T), 
        "Desviación Típica" = sd(Valor, na.rm = T),
        "Coef. Variación" = sd(Valor, na.rm = T) / mean(Valor, na.rm = T)) |>
        kable()
    Variable Media Desviación Típica Coef. Variación
    altura 1.768571 0.1150155 0.0650330
    colesterol 220.230769 39.8479482 0.1809372
    edad 38.214286 15.6213787 0.4087837
    peso 70.923077 16.1269006 0.2273858

    La variable con el coeficiente de variación más pequeño es la altura, por lo que es la que tiene la media más representativa.

  6. Realizar un resumen estadístico con el coeficiente de asimetría y el coeficiente de apuntamiento del peso y la estatura según el sexo. ¿Qué grupo tiene peso más normal, los hombres o las mujeres? ¿Y una estatura más normal?

    Con la función sumtable del paquete vtable.

    library(vtable)
    sumtable(df, vars = c("peso", "altura"), group = "sexo", summ = c('skewness(x)', 'kurtosis(x)'),
    summ.names = c("Coef. Asimetría", "Coef. Apuntamiento"))
    Warning in sumtable(df, vars = c("peso", "altura"), group = "sexo", summ = c("skewness(x)", : Factor variables ignore custom summ options. Cols 1 and 2 are count and percentage.
    Beware combining factors with a custom summ unless factor.numeric = TRUE.
    Summary Statistics
    sexo
    H
    M
    Variable Coef. Asimetría Coef. Apuntamiento Coef. Asimetría Coef. Apuntamiento
    peso 0.61 2.5 -0.47 1.9
    altura 0.27 1.9 -0.07 1.8

    Con las funciones group_by, summarise y across del paquete dplyr de tidyverse.

    library(dplyr)
    df |> select(sexo, peso, altura) |>
    group_by(sexo) |>
    summarise(across(.cols = everything(), .fns = list("Coef. Asimetría" = ~ skewness(.x, na.rm = T), "Coef. Apuntamiento" = ~ kurtosis(.x, na.rm = T)))) |>
    kable()
    sexo peso_Coef. Asimetría peso_Coef. Apuntamiento altura_Coef. Asimetría altura_Coef. Apuntamiento
    H 0.6107239 2.508255 0.2668417 1.904435
    M -0.4661293 1.852431 -0.0699589 1.756341

    Las mujeres tienen un peso más normal ya que tanto el coeficiente de asimetría como el de apuntamiento están más próximos a 0. Lo mismo ocurre con la altura.

5.2 Ejercicios propuestos

Ejercicio 5.3 El fichero renta-media-comunidades-autonomas.csv contiene información sobre la renta neta media por persona de las comunidades autónomas desde 2008 a 2021.

  1. Crear un data frame con los datos de las rentas medias por persona de las comunidades a partir del fichero renta-media-comunidades-autonomas.csv.

  2. Realizar un resumen estadístico con la media y la desviación típica, mínimo, cuartiles y máximo de todas las rentas medias.

  3. Realizar un resumen estadístico con la media y la desviación típica de las rentas medias de cada año.

  4. ¿Qué año presenta una menor variabilidad relativa?

  5. ¿En qué comunidad autónoma hay menos dispersión relativa con respecto a la media?

  6. ¿En qué comunidad autónoma es más representativa la media de las rentas?

  7. ¿Qué comunidad autónoma presenta una distribución de las rentas más normal a lo largo de los años?

  8. ¿Qué comunidades autónomas tienen una renta media por debajo del percentil 10? ¿Y cuáles tienen una renta media por encima del percentil 90?

  9. Crear la variable riqueza que clasifique las comunidades según la media de sus rentas en baja (por debajo del primer cuartil), media (entre el primer y el tercer cuartil) y alta (por encima del tercer cuartil).

  10. Hacer un resumen estadístico con la media, cuartiles, desviación típica, coeficiente de variación, coeficiente de asimetría y coeficiente de curtosis de las rentas medias según la riqueza.