4  Estadística Descriptiva

4.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.
library(kableExtra) # para personalizar el formato de las tablas.

Ejercicio 4.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 intecuartílico.

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

    R dispone de la función var para calcular la cuasivarianza o varianza corregida \(\sum \frac{(x_i-\bar x)^2}{n-1}\), 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 \(\sqrt{\sum \frac{(x_i-\bar x)^2}{n-1}}\), 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 \(g_1\) 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.

    [1] 3.71169

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

Ejercicio 4.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://raw.githubusercontent.com/asalber/estadistica-practicas-r/main/datos/colesterol.csv")
    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
    7          Antonio Fernández Ocaña   51    H   62   1.72        276
    8            Pilar Martín González   22    M   60   1.66         NA
    9             Pedro Gálvez Tenorio   35    H   90   1.94        241
    10         Santiago Reillo Manzano   46    H   75   1.85        280
    11           Macarena Álvarez Luna   53    M   55   1.62        262
    12      José María de la Guía Sanz   58    H   78   1.87        198
    13 Miguel Angel Cuadrado Gutiérrez   27    H  109   1.98        210
    14           Carolina Rubio Moreno   20    M   61   1.77        194
  2. Calcular el tamaño muestral según el sexo.

    table(df$sexo)
    
    H M 
    8 6 
    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.

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

    Usando el 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      

    Usando 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

    Usando 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 ▂▇▂▅▅

    Usando 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.3.2)
    2024-02-15

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

    Usando la función sumtable del paquete vtable.

    library(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

    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.

    Usando las funciones summarise y across del paquete dplyr.

    library(dplyr)
    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() |>
    kable_styling()
    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

    Usando las funciones group_by y summarise del paquete dplyr y pivotando el data frame a formato largo.

    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() |>
        kable_styling()
    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?

    Usando 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

    Usando las funciones group_by y summarise del paquete dplyr.

    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() |>
    kable_styling()
    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.

4.2 Ejercicios propuestos

Ejercicio 4.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.

    ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
    Rows: 19 Columns: 15
    ── Column specification ────────────────────────────────────────────────────────
    Delimiter: ";"
    chr  (1): Comunidad
    dbl (14): 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, ...
    
    ℹ Use `spec()` to retrieve the full column specification for this data.
    ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
    ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
    
    Rows: 19 Columns: 15
    ── Column specification ────────────────────────────────────────────────────────
    Delimiter: ";"
    chr  (1): Comunidad
    dbl (14): 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, ...
    
    ℹ Use `spec()` to retrieve the full column specification for this data.
    ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
    ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
    
    Rows: 19 Columns: 15
    ── Column specification ────────────────────────────────────────────────────────
    Delimiter: ";"
    chr  (1): Comunidad
    dbl (14): 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, ...
    
    ℹ Use `spec()` to retrieve the full column specification for this data.
    ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
    df <- read_csv2("https://aprendeconalf.es/estadistica-practicas-r/datos/renta-media-comunidades-autonomas.csv")
    ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
    Rows: 19 Columns: 15
    ── Column specification ────────────────────────────────────────────────────────
    Delimiter: ";"
    chr  (1): Comunidad
    dbl (14): 2021, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, ...
    
    ℹ Use `spec()` to retrieve the full column specification for this data.
    ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
    df
    # A tibble: 19 × 15
       Comunidad      `2021` `2020` `2019` `2018` `2017` `2016` `2015` `2014` `2013`
       <chr>           <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
     1 Andalucía        9915   9990   9160   9258   9116   8398   7942   8079   8408
     2 Aragón          13345  13097  12300  11990  12110  11649  12427  12037  12022
     3 Asturias Prin…  12861  12786  12523  12085  12244  12060  11427  11251  11211
     4 Balears Illes   11235  12658  12410  13240  12665  12222  10828  10660  10386
     5 Canarias        10161   9935   9487   8964   8863   8702   8640   8302   8513
     6 Cantabria       12848  12748  12205  11239  11293  10670  10494   9824   9843
     7 Castilla y Le…  12656  12697  12003  11949  11239  10815  10570  10406  10760
     8 Castilla - La…  10257  10485   9715   9533   9045   8731   8498   8545   8425
     9 Cataluña        14159  14170  13527  13338  12712  12660  12283  12205  12111
    10 Comunitat Val…  11237  11332  10611  10232   9801   9265   9098   9144   9375
    11 Extremadura      9500   9147   8796   8503   8250   8674   8469   7729   8224
    12 Galicia         11453  11469  11218  11239  10753  10439  10212  10235  10106
    13 Madrid Comuni…  14836  14580  14199  13279  13099  12647  12534  12597  12823
    14 Murcia Región…   9931   9850   8956   9111   8702   8273   7924   7767   8253
    15 Navarra Comun…  15269  15094  13937  13585  13583  13408  13300  13221  13608
    16 País Vasco      15544  15813  15300  14722  14397  14345  13836  14281  14312
    17 Rioja La        12913  13504  12697  12029  12131  11589  11132  11120  10686
    18 Ceuta           10397   9853  10164   9784   9676   9435   8512   8712   9336
    19 Melilla         12012  11427  11733  12507  10161  10883  10027  11619  11313
    # ℹ 5 more variables: `2012` <dbl>, `2011` <dbl>, `2010` <dbl>, `2009` <dbl>,
    #   `2008` <dbl>
  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.