1 Propósito y ruta de la clase

Esta clase desarrolla las páginas físicas 40–74 de Unidad_1_Series_de_tiempo.pdf.

Al terminar podrá reconocer los componentes de una serie, justificar un esquema aditivo o multiplicativo, calcular una media móvil y comparar una descomposición clásica con STL sin confundir sus escalas ni sus limitaciones.

1.1 Cómo ejecutar

Guarde el archivo en UTF-8, ábralo en RStudio y seleccione Knit → Knit to HTML. Ejecute los bloques en orden. Se utilizan R base, stats, datasets y knitr; la compilación necesita rmarkdown y Pandoc.

# Ejecutar una sola vez si faltan estos paquetes.
install.packages(c("rmarkdown", "knitr"))
rmarkdown::render("Clase_2_Componentes_y_descomposicion.Rmd")

2 Leer la serie antes de descomponerla

2.1 AirPassengers y preguntas iniciales

AirPassengers contiene 144 totales mensuales de pasajeros aéreos internacionales, de enero de 1949 a diciembre de 1960, expresados en miles de pasajeros. Es un conjunto histórico incluido en R.

y <- datasets::AirPassengers
stopifnot(length(y) == 144, frequency(y) == 12,
          !anyNA(y), all(is.finite(y)), all(y > 0))
tabla(data.frame(inicio = "1949-01", final = "1960-12",
                 observaciones = length(y), frecuencia = frequency(y),
                 unidad = "Miles de pasajeros"))
inicio final observaciones frecuencia unidad
1949-01 1960-12 144 12 Miles de pasajeros
plot(y, col = colores[1], lwd = 2, xlab = "Año",
     ylab = "Miles de pasajeros", main = "AirPassengers · datos históricos")

Antes de calcular, responda:

  1. ¿El nivel aumenta, disminuye o permanece estable?
  2. ¿Se repite un patrón en meses semejantes?
  3. ¿La amplitud cambia con el nivel?
  4. ¿Hay episodios que requieren investigación?

2.2 Ejemplo · mirar el calendario y la amplitud anual

anio <- floor(time(y) + 1e-8)
por_anio <- split(as.numeric(y), anio)
resumen_anual <- do.call(rbind, lapply(names(por_anio), function(a) {
  v <- por_anio[[a]]
  data.frame(anio = as.integer(a), nivel_medio = mean(v),
             amplitud = max(v) - min(v),
             amplitud_relativa = (max(v) - min(v)) / mean(v))
}))
tabla(resumen_anual)
anio nivel_medio amplitud amplitud_relativa
1949 126,667 44 0,347
1950 139,667 56 0,401
1951 170,167 54 0,317
1952 197,000 71 0,360
1953 225,000 92 0,409
1954 238,917 114 0,477
1955 284,000 131 0,461
1956 328,250 142 0,433
1957 368,417 166 0,451
1958 381,000 195 0,512
1959 428,333 217 0,507
1960 476,167 232 0,487
boxplot(as.numeric(y) ~ factor(cycle(y), levels = 1:12, labels = meses),
        xlab = "Mes", ylab = "Miles de pasajeros",
        col = "#E8EFEA", main = "Distribución por mes en todos los años")

La amplitud relativa facilita la comparación entre niveles distintos. Estos resúmenes son exploratorios: el rango anual también recoge tendencia y ruido. El diagrama por mes mezcla años de niveles distintos y no estima por sí solo un efecto estacional depurado de tendencia.

3 Componentes y elección del esquema

3.1 Tendencia, ciclo, estacionalidad e irregularidad

En la representación conceptual aditiva:

\[y_t=T_t+C_t+S_t+R_t=M_t+S_t+R_t,\qquad M_t=T_t+C_t.\]

Componente Qué describe Qué debe evitarse
Tendencia Evolución sostenida del nivel Suponer que siempre es una recta
Ciclo Oscilaciones sin duración fija de calendario Equipararlo a una estación del año
Estacionalidad Patrón ligado al calendario Afirmar que toda oscilación es estacional
Irregularidad o resto Lo que el procedimiento no explica Dar por demostrada su independencia

La separación de tendencia y ciclo exige supuestos adicionales. decompose() y stl() devuelven una componente suavizada llamada trend; en esta clase se interpreta como tendencia-ciclo, no como una identificación separada de ambos.

3.2 Ejemplo · construir una serie con componentes conocidos

set.seed(2040)
t <- 1:120
T_real <- 100 + 1.2 * t
# La fase cambia: esta oscilación no sigue un ciclo anual fijo.
C_real <- 12 * sin(2 * pi * (t / 45 + 0.000035 * t^2))
S_real <- 10 * sin(2 * pi * t / 12)
R_real <- rnorm(length(t), sd = 3)
y_sim <- ts(T_real + C_real + S_real + R_real,
            start = c(2015, 1), frequency = 12)
componentes_reales <- lapply(list(as.numeric(y_sim), T_real + C_real,
                                S_real, R_real),
                            ts, start = c(2015, 1), frequency = 12)
paneles(componentes_reales,
        c("Serie simulada", "Tendencia y ciclo conocidos",
          "Estacionalidad anual conocida", "Irregularidad simulada"),
        rep("Unidades", 4), c(NA, NA, 0, 0))

stopifnot(max(abs(as.numeric(y_sim) - T_real - C_real - S_real - R_real)) < 1e-10)

Explique: conocemos los componentes porque los construimos. Con una serie real observamos su suma y debemos estimarlos; diferentes métodos pueden producir descomposiciones distintas del mismo registro.

3.3 Amplitud constante o proporcional

Compare:

\[\text{Aditivo: } y_t=M_t+S_t+R_t,\qquad \text{Multiplicativo: } y_t=M_tS_tR_t.\]

En el esquema aditivo todos los componentes conservan la unidad de la serie. En el multiplicativo, \(M_t\) conserva esa unidad y \(S_t,R_t\) son factores. Para aplicar logaritmos se requieren valores estrictamente positivos.

t60 <- 1:60
nivel <- 100 + 2 * t60
serie_A <- nivel + 10 * sin(2 * pi * t60 / 12)
serie_B <- nivel * (1 + 0.10 * sin(2 * pi * t60 / 12))
matplot(t60, cbind(serie_A, serie_B), type = "l", lty = c(1, 2), lwd = 2,
        col = colores[1:2], xlab = "Mes", ylab = "Unidades",
        main = "Ejercicio de las diapositivas · amplitud absoluta y relativa")
legend("topleft", c("A: +/-10 unidades", "B: +/-10 % del nivel"),
       col = colores[1:2], lty = c(1, 2), bty = "n")

Preguntas: elija un esquema para A y otro para B. Justifique la elección y explique qué revisaría antes de usar log(). Un cero no se reemplaza por un número arbitrario solo para poder transformar la serie.

3.4 Dos ejemplos numéricos resueltos

Desestacionalizar significa retirar \(S_t\):

\[y_t^{SA}=y_t-S_t\quad\text{o}\quad y_t^{SA}=y_t/S_t.\]

M_a <- 200; S_a <- 30; R_a <- -5
observado_a <- M_a + S_a + R_a
ajustado_a <- observado_a - S_a
M_m <- 200; S_m <- 1.20; R_m <- .95
observado_m <- M_m * S_m * R_m
ajustado_m <- observado_m / S_m
tabla(data.frame(esquema = c("Aditivo", "Multiplicativo"),
                 observado = c(observado_a, observado_m),
                 desestacionalizado = c(ajustado_a, ajustado_m)))
esquema observado desestacionalizado
Aditivo 225 195
Multiplicativo 228 190
stopifnot(observado_a == 225, ajustado_a == 195,
          abs(observado_m - 228) < 1e-10, abs(ajustado_m - 190) < 1e-10)

El desestacionalizado es 195 o 190, no 200: conserva el resto además de la tendencia-ciclo. Un factor de 1,20 representa una contribución estacional de 20 % sobre la base multiplicativa; el valor observado también depende de \(R_t\).

4 Medias móviles y descomposición clásica

4.1 Media móvil centrada de tres términos

\[\widehat M_t=\frac{y_{t-1}+y_t+y_{t+1}}{3}.\]

x_corto <- c(10, 13, 16, 13, 10)
mm3 <- stats::filter(x_corto, filter = rep(1/3, 3), sides = 2)
tabla(data.frame(t = 1:5, y = x_corto, media_centrada_3 = as.numeric(mm3)))
t y media_centrada_3
1 10 NA
2 13 13
3 16 14
4 13 13
5 10 NA
stopifnot(is.na(mm3[1]), is.na(mm3[5]),
          max(abs(as.numeric(mm3[2:4]) - c(13, 14, 13))) < 1e-10)

En \(t=3\), \((13+16+13)/3=14\). Los extremos son NA porque no se dispone de vecinos suficientes. No son ceros ni se completan automáticamente con la media.

4.2 Ejemplo el efecto del ancho de la ventana

suave3 <- stats::filter(y_sim, rep(1/3, 3), sides = 2)
suave13 <- stats::filter(y_sim, rep(1/13, 13), sides = 2)
ts.plot(y_sim, suave3, suave13, col = c("gray70", colores[1:2]),
        lty = c(1, 1, 2), xlab = "Año", ylab = "Unidades",
        main = "Simulación · suavizar cambia el detalle visible")
legend("topleft", c("Serie", "Ventana 3", "Ventana 13"),
       col = c("gray70", colores[1:2]), lty = c(1, 1, 2), bty = "n")

Una ventana mayor suaviza más y pierde más observaciones en los bordes. La media uniforme de 13 términos de este ejemplo no es el filtro 2×12 utilizado a continuación.

4.3 Centrar una ventana par

El promedio de 12 meses se sitúa entre dos instantes. Al promediar dos medias contiguas de 12 términos se obtiene una media centrada 2×12:

\[\widehat M_t=\frac{y_{t-6}}{24} +\frac{1}{12}\sum_{j=-5}^{5}y_{t+j} +\frac{y_{t+6}}{24}.\]

pesos_2x12 <- c(.5, rep(1, 11), .5) / 12
stopifnot(length(pesos_2x12) == 13, abs(sum(pesos_2x12) - 1) < 1e-12)
M_2x12 <- stats::filter(y, filter = pesos_2x12, sides = 2)
pos <- 20L
manual <- mean(c(mean(y[(pos - 6):(pos + 5)]),
                 mean(y[(pos - 5):(pos + 6)])))
tabla(data.frame(posicion = pos, calculo_manual = manual,
                 filtro = as.numeric(M_2x12[pos]),
                 extremos_sin_estimacion = sum(is.na(M_2x12))))
posicion calculo_manual filtro extremos_sin_estimacion
20 143,167 143,167 12
stopifnot(abs(manual - M_2x12[pos]) < 1e-10, sum(is.na(M_2x12)) == 12)

Hay seis valores sin estimar al principio y seis al final. El filtro usa datos posteriores a \(t\): sirve para descripción retrospectiva, pero no como si fuera una estimación disponible en tiempo real.

4.4 Efectos estacionales trimestrales

La normalización identifica una escala de referencia: \(\sum_{j=1}^{s}S_j=0\) en el aditivo y \(s^{-1}\sum_{j=1}^{s}S_j=1\) en el multiplicativo clásico.

efecto <- c(-15, 5, 20, -10)
factor <- c(.85, 1.05, 1.20, .90)
tabla(data.frame(trimestre = paste0("T", 1:4), efecto_aditivo = efecto,
                 factor_multiplicativo = factor,
                 contribucion_pct = 100 * (factor - 1)))
trimestre efecto_aditivo factor_multiplicativo contribucion_pct
T1 -15 0,85 -15
T2 5 1,05 5
T3 20 1,20 20
T4 -10 0,90 -10
stopifnot(sum(efecto) == 0, abs(mean(factor) - 1) < 1e-12)
# Ampliación: normalizar estimaciones preliminares.
preliminar_a <- c(-12, 8, 23, -7)
preliminar_m <- c(.90, 1.10, 1.25, .95)
tabla(data.frame(trimestre = 1:4,
                 aditivo_normalizado = preliminar_a - mean(preliminar_a),
                 multiplicativo_normalizado = preliminar_m / mean(preliminar_m)))
trimestre aditivo_normalizado multiplicativo_normalizado
1 -15 0,857
2 5 1,048
3 20 1,190
4 -10 0,905

5 AirPassengers paso a paso

5.1 Procedimiento clásico multiplicativo

Primero se estima \(M_t\), luego se calcula \(y_t/M_t\), se promedia por mes, se normalizan los factores y se obtiene \(R_t=y_t/(\widehat M_t\widehat S_t)\).

dc <- stats::decompose(y, type = "multiplicative")
y_sa <- y / dc$seasonal
paneles(list(y, dc$trend, dc$seasonal, dc$random),
        c("Serie observada", "Tendencia-ciclo clásica",
          "Factor estacional", "Resto multiplicativo"),
        c("Miles de pasajeros", "Miles de pasajeros", "Factor", "Factor"),
        c(NA, NA, 1, 1))

cociente <- y / M_2x12
factor_preliminar <- tapply(as.numeric(cociente), cycle(y), mean, na.rm = TRUE)
factor_manual <- factor_preliminar / mean(factor_preliminar)
stopifnot(max(abs(factor_manual - dc$figure)) < 1e-10,
          max(abs(M_2x12 - dc$trend), na.rm = TRUE) < 1e-10,
          max(abs(y - dc$trend * dc$seasonal * dc$random), na.rm = TRUE) < 1e-10)
tabla(data.frame(mes = meses, factor = as.numeric(dc$figure),
                 contribucion_estacional_pct = 100 * (as.numeric(dc$figure) - 1)))
mes factor contribucion_estacional_pct
Ene 0,910 -8,977
Feb 0,884 -11,637
Mar 1,007 0,737
Abr 0,976 -2,409
May 0,981 -1,862
Jun 1,113 11,278
Jul 1,227 22,656
Ago 1,220 21,991
Sep 1,060 6,049
Oct 0,922 -7,824
Nov 0,801 -19,882
Dic 0,899 -10,118
barplot(dc$figure, names.arg = meses, col = colores[1],
        ylab = "Factor estacional", xlab = "Mes", ylim = c(0, 1.5),
        main = "AirPassengers · patrón mensual clásico")
abline(h = 1, lty = 2)

La media de los 12 factores es 1. El patrón se repite cada año por construcción. Un factor superior a 1 es una contribución estacional positiva, pero no obliga a que cada observación supere \(M_t\), porque también interviene el resto.

ts.plot(y, y_sa, col = colores[1:2], lty = c(1, 2), lwd = 2,
        xlab = "Año", ylab = "Miles de pasajeros",
        main = "Desestacionalizar conserva la tendencia")
legend("topleft", c("Observada", "Desestacionalizada"),
       col = colores[1:2], lty = c(1, 2), bty = "n")

Lectura: random es el nombre del componente en R; no prueba aleatoriedad independiente. El resto multiplicativo se interpreta alrededor de 1. Los NA de sus extremos provienen de la tendencia-ciclo no estimada.

5.2 Logaritmos y STL

\[\log(y_t)=\log(M_t)+\log(S_t)+\log(R_t).\]

z <- log(y)
ajuste <- stats::stl(z, s.window = "periodic", robust = TRUE)
componentes <- ajuste$time.series
paneles(list(z, componentes[, "trend"], componentes[, "seasonal"],
             componentes[, "remainder"]),
        c("Logaritmo de AirPassengers", "Tendencia-ciclo STL",
          "Estacionalidad STL", "Resto STL"),
        rep("Escala log", 4), c(NA, NA, 0, 0))

tabla(head(componentes))
seasonal trend remainder
-0,083882194 4,803064 -0,0006826642
-0,142365972 4,806942 0,1061089448
0,025284297 4,810820 0,0466980517
-0,012521162 4,815287 0,0570465061
-0,007673679 4,819755 -0,0162903219
0,114808208 4,824574 -0,0341070611
stopifnot(max(abs(z - rowSums(componentes))) < 1e-10)

Aquí s.window = "periodic" impone una estacionalidad fija. Aunque STL puede permitir que cambie, esta configuración no lo hace. robust = TRUE reduce la influencia de observaciones atípicas durante el ajuste; no las elimina del registro.

factor_stl <- exp(componentes[, "seasonal"])
y_sa_stl <- exp(z - componentes[, "seasonal"])
tabla(data.frame(fecha = seq(as.Date("1949-01-01"), by = "month", length.out = 6),
                 observado = as.numeric(y[1:6]),
                 factor_stl = as.numeric(factor_stl[1:6]),
                 ajustado_stl = as.numeric(y_sa_stl[1:6])))
fecha observado factor_stl ajustado_stl
1949-01-01 112 0,920 121,800
1949-02-01 118 0,867 136,054
1949-03-01 132 1,026 128,704
1949-04-01 129 0,988 130,625
1949-05-01 121 0,992 121,932
1949-06-01 135 1,122 120,358
stopifnot(max(abs(y_sa_stl - y / factor_stl)) < 1e-10)

Al exponenciar, los efectos logarítmicos se vuelven factores. Su normalización no debe confundirse con la media aritmética igual a 1 de decompose(). Esta es una identidad de descomposición observada, no un pronóstico de la media: exponenciar un pronóstico logarítmico requeriría considerar el sesgo de la transformación inversa.

5.3 Ejemplo · estacionalidad que cambia y un atípico

set.seed(2067)
tt <- 1:180
base_log <- 4.5 + .003 * tt
estacional_log <- (.06 + .0005 * tt) * sin(2 * pi * tt / 12)
log_sim <- base_log + estacional_log + rnorm(180, sd = .015)
log_sim[95] <- log_sim[95] + .65
log_sim <- ts(log_sim, start = c(2000, 1), frequency = 12)
stl_fijo <- stl(log_sim, s.window = "periodic", robust = TRUE)
stl_flexible <- stl(log_sim, s.window = 7, robust = TRUE)
stl_no_robusto <- stl(log_sim, s.window = 7, robust = FALSE)
paneles(list(stl_fijo$time.series[, "seasonal"],
             stl_flexible$time.series[, "seasonal"],
             stl_flexible$time.series[, "remainder"]),
        c("Patrón fijo estimado", "Patrón variable estimado",
          "El atípico permanece visible en el resto robusto"),
        rep("Escala log", 3), c(0, 0, 0))

tabla(data.frame(metodo = c("Flexible robusto", "Flexible no robusto"),
                 tendencia_en_95 = c(stl_flexible$time.series[95, "trend"],
                                      stl_no_robusto$time.series[95, "trend"]),
                 tendencia_conocida = base_log[95]))
metodo tendencia_en_95 tendencia_conocida
Flexible robusto 4,782 4,785
Flexible no robusto 4,836 4,785

La ventana estacional numérica trabaja sobre subseries de la misma estación; 7 no significa un promedio móvil simple de siete meses consecutivos. Compare la estimación con la estructura conocida, sin concluir que una opción será siempre mejor para cualquier serie.

6 Comparar métodos sin confundir las unidades

6.1 Taller aditivo frente a multiplicativo

da <- decompose(y, type = "additive")
dm <- decompose(y, type = "multiplicative")
paneles(list(da$random, dm$random), c("Resto aditivo", "Resto multiplicativo"),
        c("Miles de pasajeros", "Factor"), c(0, 1))

Pregunta ¿son comparables las escalas de los dos restos?

No se debe elegir el método con la varianza numéricamente menor: uno está en miles de pasajeros y el otro es un factor sin unidades.

6.2 Ejemplo · comparación relativa y fechas comunes

base_aditiva <- da$trend + da$seasonal
rel_a <- da$random / base_aditiva
rel_m <- dm$random - 1
rel_stl <- exp(componentes[, "remainder"]) - 1
comunes <- is.finite(rel_a) & is.finite(rel_m) & is.finite(rel_stl)
stopifnot(all(base_aditiva[comunes] > 0))
tabla(data.frame(metodo = c("Clásico aditivo", "Clásico multiplicativo", "STL log"),
                 n_comun = sum(comunes),
                 mediana_abs_resto_relativo =
                   c(median(abs(rel_a[comunes])), median(abs(rel_m[comunes])),
                     median(abs(rel_stl[comunes])))))
metodo n_comun mediana_abs_resto_relativo
Clásico aditivo 132 0,042
Clásico multiplicativo 132 0,017
STL log 132 0,016

Ahora se describen desviaciones relativas respecto de bases estimadas por cada método, en las mismas fechas. La tabla no mide precisión predictiva ni prueba independencia: la flexibilidad de cada ajuste también afecta su resto.

6.3 Ejemplo · una media centrada puede mirar al futuro

En el periodo 20 todavía no conocemos el 21.

historia <- as.numeric(y[1:36])
historia_alterada <- historia
historia_alterada[21] <- historia_alterada[21] + 90
filtrar <- function(v, lados) as.numeric(stats::filter(v, rep(1/3, 3), sides = lados))
comparacion_filtro <- data.frame(
  filtro = c("Centrado", "Solo presente y pasado"),
  valor_t20 = c(filtrar(historia, 2)[20], filtrar(historia, 1)[20]),
  t20_tras_cambiar_t21 = c(filtrar(historia_alterada, 2)[20],
                          filtrar(historia_alterada, 1)[20]))
tabla(comparacion_filtro)
filtro valor_t20 t20_tras_cambiar_t21
Centrado 166 196
Solo presente y pasado 163 163
stopifnot(abs(diff(as.numeric(comparacion_filtro[2, 2:3]))) < 1e-10,
          abs(comparacion_filtro[1, 3] - comparacion_filtro[1, 2] - 30) < 1e-10)

Cambiar un dato futuro altera el suavizado centrado del pasado. Para evaluar predicciones hay que ajustar cada transformación usando solo la muestra de entrenamiento disponible en ese origen. El filtro unilateral sí utiliza información disponible, pero tiene propiedades y retraso diferentes.

7 Práctica

7.1 A · Reproducir el taller

y_practica <- datasets::AirPassengers
practica_a <- decompose(y_practica, type = "additive")
practica_m <- decompose(y_practica, type = "multiplicative")
tabla(data.frame(mes = meses, efecto_aditivo = practica_a$figure,
                 factor_multiplicativo = practica_m$figure))
mes efecto_aditivo factor_multiplicativo
Ene -24,749 0,910
Feb -36,188 0,884
Mar -2,241 1,007
Abr -8,037 0,976
May -4,506 0,981
Jun 35,403 1,113
Jul 63,831 1,227
Ago 62,823 1,220
Sep 16,520 1,060
Oct -20,643 0,922
Nov -53,593 0,801
Dic -28,620 0,899
  1. Describa frecuencia, unidad, periodo y longitud.
  2. Justifique si elegiría un esquema aditivo o multiplicativo.
  3. Interprete dos meses con efectos diferentes, indicando las unidades.
  4. Explique los valores ausentes de los extremos y las escalas de los restos.

7.2 C · Comparación con STL

practica_stl <- stl(log(y_practica), s.window = "periodic", robust = TRUE)
sa_clasica <- y_practica / practica_m$seasonal
sa_stl <- exp(log(y_practica) - practica_stl$time.series[, "seasonal"])
ts.plot(sa_clasica, sa_stl, col = colores[1:2], lty = c(1, 2),
        xlab = "Año", ylab = "Miles de pasajeros",
        main = "Práctica · series desestacionalizadas")
legend("topleft", c("Clásica multiplicativa", "STL log"),
       col = colores[1:2], lty = c(1, 2), bty = "n")

Responda las preguntas de la página 68: ¿el resto conserva oscilaciones?, ¿parece estable el patrón estacional?, ¿los extremos tienen menos información?, ¿cambian las conclusiones al transformar?

Modificación adicional: repita STL con s.window = 7. Explique qué supuesto cambió y por qué no debe decidir únicamente por el tamaño del resto.

7.3 Ampliación autónoma · una serie trimestral conocida

set.seed(2074)
tr <- 1:40
ventas_tr <- ts(200 + 3 * tr + rep(c(-15, 5, 20, -10), 10) +
                 rnorm(40, sd = 2), start = c(2016, 1), frequency = 4)
ajuste_tr <- decompose(ventas_tr, type = "additive")
tabla(data.frame(trimestre = paste0("T", 1:4),
                 efecto_real = c(-15, 5, 20, -10),
                 efecto_estimado = ajuste_tr$figure))
trimestre efecto_real efecto_estimado
T1 -15 -16,017
T2 5 6,143
T3 20 19,734
T4 -10 -9,860

Explique por qué el efecto estimado puede diferir del utilizado en la simulación. Cambie la desviación del ruido de 2 a 8 manteniendo la semilla; compare las estimaciones. Conservar el mismo mecanismo permite estudiar el efecto del ruido.

Documentación para consultar métodos y datos:

#> R version 4.5.1 (2025-06-13 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#> 
#> Matrix products: default
#>   LAPACK version 3.12.1
#> 
#> locale:
#> [1] LC_COLLATE=Spanish_Ecuador.utf8  LC_CTYPE=Spanish_Ecuador.utf8   
#> [3] LC_MONETARY=Spanish_Ecuador.utf8 LC_NUMERIC=C                    
#> [5] LC_TIME=Spanish_Ecuador.utf8    
#> 
#> time zone: America/Guayaquil
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] digest_0.6.39     R6_2.6.1          fastmap_1.2.0     xfun_0.58         cachem_1.1.0     
#>  [6] knitr_1.51        htmltools_0.5.9   rmarkdown_2.31    lifecycle_1.0.5   cli_3.6.6        
#> [11] sass_0.4.10       jquerylib_0.1.4   compiler_4.5.1    rstudioapi_0.18.0 tools_4.5.1      
#> [16] evaluate_1.0.5    bslib_0.11.0      yaml_2.3.12       otel_0.2.0        jsonlite_2.0.0   
#> [21] rlang_1.2.0