INTRODUCCIÓN

En muchas ocasiones es necesario calcular un determinado estadístico en función de una o varias variables, con el fin de poder establecer comparaciones entre esos subconjuntos.

En este tema abordamos el cálculo de estadísticos descriptivos aplicados a subconjuntos de datos, utilizando herramientas modernas del ecosistema tidyverse, principalmente:

Estas funciones sustituyen a las tradicionales subset(), aggregate(), tapply() y otras de base R.

Por ejemplo, imaginemos la siguiente una base de datos. En primer lugar, generaremos la base de datos con esas variables.

⚠️ ESTABLECER SEMILLA:

Para que los resultados de algunos cálculos sean idénticos a los mostrados en la página web, es necesario iniciar cada actividad estableciendo una semilla que asegure su reproducibilidad.

set.seed(123)
library(dplyr)
dataset <- data.frame(contaminante = round(rnorm(100, sd = 10, mean = 30)),
                     estacion = sample(c("invierno","primavera","verano", "otoño"), size = 100, replace = TRUE),
                     localidad = sample(paste("localidad", 1:4),
                                        size = 100, 
                                        replace = TRUE))
head(dataset)
##   contaminante  estacion   localidad
## 1           24 primavera localidad 2
## 2           28 primavera localidad 2
## 3           46     otoño localidad 1
## 4           31  invierno localidad 2
## 5           31     otoño localidad 1
## 6           47     otoño localidad 1
str(dataset)
## 'data.frame':    100 obs. of  3 variables:
##  $ contaminante: num  24 28 46 31 31 47 35 17 23 26 ...
##  $ estacion    : chr  "primavera" "primavera" "otoño" "invierno" ...
##  $ localidad   : chr  "localidad 2" "localidad 2" "localidad 1" "localidad 2" ...

Esta base de datos contiene las siguiente variables:

Existen diferentes posibilidades para calcular esos valores desagregados según otras variables.

Por ejemplo, para el cálculo de la concentracion de contaminantes según la estación del año.

dataset %>%
  group_by(estacion) %>%
  summarise(
    media = mean(contaminante),
    sd = sd(contaminante),
    n = n(),
    .groups = "drop")
## # A tibble: 4 × 4
##   estacion  media    sd     n
##   <chr>     <dbl> <dbl> <int>
## 1 invierno   29.6  9.72    32
## 2 otoño      34.0  8.85    25
## 3 primavera  30.5  8.65    24
## 4 verano     29.6  8.86    19

Una alternativa es calcular el promedio y la desviación típica según la localidad

dataset %>%
  group_by(localidad) %>%
  summarise(
    media = mean(contaminante),
    sd = sd(contaminante),
    n = n(),
    .groups = "drop"
  )
## # A tibble: 4 × 4
##   localidad   media    sd     n
##   <chr>       <dbl> <dbl> <int>
## 1 localidad 1  29.9  8.66    37
## 2 localidad 2  30.3  8.67    25
## 3 localidad 3  31.4 12.4     20
## 4 localidad 4  33.4  6.42    18

Y también podríamos calcular el promedio por estación y localidad

dataset %>%
  group_by(estacion, localidad) %>%
  summarise(
    media = mean(contaminante),
    sd = sd(contaminante),
    n = n(),
    .groups = "drop"
  )
## # A tibble: 16 × 5
##    estacion  localidad   media    sd     n
##    <chr>     <chr>       <dbl> <dbl> <int>
##  1 invierno  localidad 1  30.7  9.57    10
##  2 invierno  localidad 2  26.1  9.31     8
##  3 invierno  localidad 3  26.6 11.9      7
##  4 invierno  localidad 4  34.9  6.82     7
##  5 otoño     localidad 1  31.6  8.36    13
##  6 otoño     localidad 2  41    9.90     2
##  7 otoño     localidad 3  39.7 13.1      3
##  8 otoño     localidad 4  34.1  7.45     7
##  9 primavera localidad 1  28    8.41     4
## 10 primavera localidad 2  28.7  5.66    10
## 11 primavera localidad 3  33.9 12.3      8
## 12 primavera localidad 4  31.5  2.12     2
## 13 verano    localidad 1  27.5  8.86    10
## 14 verano    localidad 2  35.8  8.14     5
## 15 verano    localidad 3  26.5 13.4      2
## 16 verano    localidad 4  28    0        2

La opción .groups = “drop” dentro de summarise() controla qué ocurre con los grupos después de resumir.Cuando ejecutamos summarise() el resultado sigue estando “agrupado” por estacion, aunque ya solo queda una fila por grupo. Esto a veces no es deseable, porque:

El argumento groups = "drop" le indica a dplyr que desagrupes completamente el resultado después del resumen.

Si quisiéramos calcular los deciles extremos la sintaxis sería la siguiente:

dataset %>%
  group_by(localidad) %>%
  summarise(
    decil_10 = quantile(contaminante, 0.10, na.rm = TRUE),
    decil_90 = quantile(contaminante, 0.90, na.rm = TRUE),
    .groups = "drop")
## # A tibble: 4 × 3
##   localidad   decil_10 decil_90
##   <chr>          <dbl>    <dbl>
## 1 localidad 1     19.6     41  
## 2 localidad 2     19.4     41.2
## 3 localidad 3     16.6     45.7
## 4 localidad 4     26.1     41.3
media_2_factores <- dataset %>%
  group_by(estacion, localidad) %>%
  summarise(
    media_contaminante = mean(contaminante, na.rm = TRUE),
    .groups = "drop")
diferentes_estadisticos <- dataset %>%
  group_by(estacion, localidad) %>%
  summarise(
    suma  = sum(contaminante, na.rm = TRUE),
    media = mean(contaminante, na.rm = TRUE),
    sd    = sd(contaminante, na.rm = TRUE),
    .groups = "drop")

📝 ACTIVIDAD DE EVALUACIÓN CONTINUA:

EJERCICIO 1. A partir del dataframe zonas_verdes calcula:

  • El número total de parques en cada barrio

  • La superficie media, la superficie mediana, los percentiles 25 y 75, la desviación típica y el coeficiente de variación de la superficie según barrios.

  • El número máximo y mínimo de parques en obras/sin obras según barrio.

EJERCICIO 2.

  • A partir del dataframe airquality calcula el valor medio mensual de las variables Temp, Ozone, Solar.R y Wind.

  • Filtrar los días con Ozone mayor de 100

  • Filtrar los días de julio y agosto con Wind < 10

  • Seleccionar solo Ozone, Wind y Temp

  • Seleccionar todas las variables menos Solar.R

  • Crear una variable que indique si la temperatura es alta (>85°F)

  • Crear un índice de confort térmico (Temp / Wind)

  • Calcular la media, mediana y desviación típica mensual del ozono

  • Calcular el número de días válidos (no NA) por mes y por variable

  • Encontrar el día más cálido de cada mes

  • Encontrar el día con el ozono mínimo de cada mes

  • Ordenar los días por contaminación (Ozone) de mayor a menor

  • Rellenar los valores NA de Ozone con la media mensual

  • Calcular el rango intercuartílico de Temp por mes

  • Detectar valores atípicos de Ozone usando 1.5 × IQR

  • Estandarizar cada variable numérica

  • Obtener el total de días con Temp > 90 por mes

  • Crear categorías de ozono: bajo, medio, alto (terciles)

  • Calcular medias mensuales para todas las variables con across()

  • Calcular anomalías respecto a la media mensual (valor – media del mes)

Filtrar los días con Ozone mayor de 100