
Tutorial 4: Creación de Variables y Agregación Temporal
Equipo climasus4r
17/10/2026
Source:vignettes/04-variaveis-agregacao.Rmd
04-variaveis-agregacao.RmdObjetivo
Al final de este tutorial serás capaz de transformar microdatos individuales en una serie temporal lista para análisis. Son dos operaciones encadenadas y dos de visualización:
-
Crear variables derivadas —
sus_data_create_variables()— generando grupos de edad (definidos por el usuario, de riesgo climático y quinquenales del IBGE) y variables de calendario (año, mes, trimestre, estación del año); -
Agregar en el tiempo y en el espacio —
sus_data_aggregate()— convirtiendo los registros individuales en conteos por período y por municipio (diaria, mensual, estacional, etc.); -
Visualizar la serie temporal —
sus_data_plot_aggregate_ts()— con curvas epidémicas, boxplots estacionales, mapas de calor de calendario y tendencias anuales; -
Visualizar la distribución espacial —
sus_data_plot_aggregate_map()— con mapas de burbujas o coropléticos municipales.
Esta es la cuarta etapa del pipeline
(derive → aggregate). Ocupa un lugar crítico: es aquí donde
los datos dejan de ser una tabla de eventos individuales y pasan a tener
la forma exigida por los modelos clima–salud del Tutorial 9 (un conteo
por unidad de tiempo
).
Contexto científico
Los estudios de series temporales en epidemiología ambiental modelan el conteo de desenlaces por período (por ejemplo, muertes por día) en función de la exposición ambiental (temperatura, contaminación). Para ello, los microdatos deben ser agregados en una grilla temporal regular y, con frecuencia, estratificados por grupo de edad, ya que la vulnerabilidad al calor y al frío varía mucho con la edad (Gasparrini et al., 2015; Bhaskaran et al., 2013).
Dos decisiones metodológicas de esta etapa tienen consecuencias directas en el análisis:
-
La unidad temporal de agregación
(
time_unit) define la resolución del estudio. Las series diarias captan efectos agudos de corto plazo (ideales para DLNM); las series mensuales o estacionales evidencian patrones de largo plazo y estacionalidad (Bhaskaran et al., 2013). -
El relleno de fechas faltantes
(
complete_dates = TRUE) garantiza una serie sin lagunas: los días sin ninguna muerte reciben conteo cero. Sin esto, los modelos de serie temporal interpretarían erróneamente la ausencia de una fecha como ausencia de información, y no como un cero verdadero.
Los grupos de edad siguen categorizaciones reconocidas — incluyendo la estructura quinquenal del IBGE (0–4, 5–9, …, 80+), que asegura comparabilidad nacional e internacional — y un grupo de riesgo climático (0–4, 5–64, 65+) diseñado para destacar a los grupos más vulnerables (IBGE, 2010; WHO, 2014).
Caso conductor. Investigamos la temperatura y los desenlaces de salud en adultos mayores (60+) en la Región Metropolitana de São Paulo, 2014–2019. Partiendo de las muertes respiratorias de adultos mayores ya filtradas en el Tutorial 3 (
caso_filtrado.rds), creamos grupos de edad (60–69, 70–79, 80+) y variables de calendario, y agregamos en serie diaria (todas las muertes) y en serie mensual por grupo de edad. La serie resultante (caso_serie.rds) alimenta la unión espacial (Tutorial 5) y, más adelante, el modelado (Tutorial 9).
Datos utilizados
| Ítem | Detalle |
|---|---|
| Entrada |
dados/caso_filtrado.rds (salida del Tutorial 3) |
| Desenlace | Muertes respiratorias (CID-10 J00–J99) en adultos mayores 60+ |
| Sistema | SIM-DO (mortalidad) |
| Recorte | Región Metropolitana de São Paulo, 2014–2019 |
| Salida |
dados/caso_serie.rds (entrada del Tutorial 5) |
Si el Tutorial 3 aún no ha sido ejecutado, el script de generación
avisa y continúa con un ejemplo mínimo sintético que
tiene la misma estructura de columnas estandarizadas
(data_obito, codigo_municipio_residencia,
idade, sexo, causa_basica) — así
la etapa se ilustra de punta a punta.
Pipeline completo
Los bloques de abajo reproducen lo que ejecuta el script
scripts/tutorial_04_variaveis_agregacao.R. Comienza
cargando el paquete:
library(climasus4r)Cargar la salida de la etapa anterior
caso_filtrado <- sus_data_read("output/caso_filtrado.parquet")
# ou, no fluxo dos tutoriais, readRDS("vignettes-pt/dados/caso_filtrado.rds")
obitos <- caso_filtrado # climasus_df no stage "filter_cid"/"stand"Crear variables derivadas
sus_data_create_variables() crea grupos de edad y
variables de calendario en una sola llamada. Aquí usamos grupos
orientados al recorte de adultos mayores del caso conductor y vinculamos
las variables estacionales con la región climática
"sudeste".
obitos_vars <- sus_data_create_variables(
obitos,
create_age_groups = TRUE,
age_breaks = c(60, 70, 80, Inf), # idosos jovens / 70-79 / 80+
age_labels = c("60-69", "70-79", "80+"),
create_calendar_vars = TRUE, # ano, mes, trimestre, ...
create_climate_vars = TRUE, # estação do ano
climate_region = "sudeste", # região climática do caso
hemisphere = "south", # Brasil
backend = "tibble",
lang = "pt"
)Además de age_group (definida por
age_breaks/age_labels), la función crea
automáticamente el grupo de riesgo climático
(grupo_risco_climatico) y el grupo quinquenal del
IBGE (faixa_etaria_ibge), y — con
create_calendar_vars = TRUE — las variables
ano, mes, trimestre y la estación
del año (estacao_climatica +
estacao_seca_chuvosa cuando se informa
climate_region; si no,
estacao_astronomica).
Agregar en serie temporal diaria
sus_data_aggregate() convierte los registros
individuales en conteos. Con fun = "count" y sistema SIM,
la columna agregada se nombra automáticamente como
n_obitos. complete_dates = TRUE rellena los
días sin muertes con cero.
serie_diaria <- sus_data_aggregate(
obitos_vars,
time_unit = "day", # uma observação por dia
fun = "count", # contagem de óbitos
group_by = NULL, # agrega no código de município detectado
complete_dates = TRUE, # preenche dias sem evento com zero
backend = "tibble",
lang = "pt"
)Agregar en serie mensual por grupo de edad
La misma función, ahora estratificando por age_group.
Esta es la serie que se guarda para el próximo tutorial.
serie_mensal <- sus_data_aggregate(
obitos_vars,
time_unit = "month",
fun = "count",
group_by = "age_group", # faixa etária criada acima
complete_dates = TRUE,
backend = "tibble",
lang = "pt"
)Visualizar la serie temporal
sus_data_plot_aggregate_ts() recibe un
climasus_df en el stage "aggregate" y produce
gráficos de calidad de publicación. plot_type acepta
"epidemic", "seasonal", "heatmap"
y "trend" (y combinaciones, vía
patchwork).
# Curva epidêmica diária com suavização loess
sus_data_plot_aggregate_ts(
serie_diaria,
plot_type = "epidemic",
smooth_method = "loess",
palette = "lancet",
lang = "pt"
)
# Boxplot da distribuição sazonal mensal
sus_data_plot_aggregate_ts(
serie_diaria,
plot_type = "seasonal",
lang = "pt"
)Visualizar la distribución espacial
sus_data_plot_aggregate_map() mapea los conteos por
municipio. Para ello, agregamos preservando el código de
municipio como variable de grupo.
serie_muni <- sus_data_aggregate(
obitos_vars,
time_unit = "month",
fun = "count",
group_by = "codigo_municipio_residencia",
backend = "tibble",
lang = "pt"
)
sus_data_plot_aggregate_map(
serie_muni,
map_type = "bubble", # não exige geobr/sf
log_scale = TRUE,
palette = "YlOrRd",
lang = "pt"
)Al final de esta etapa tenemos serie_mensal (por grupo
de edad) y serie_muni (por municipio) — la base
temporal/espacial que alimenta los próximos tutoriales.
Características de las funciones
sus_data_create_variables()
Crea variables derivadas a partir de la edad y de la fecha del
evento. Requiere que los datos estén en el stage "stand" (o
posterior).
| Argumento | ¿Esencial? | Descripción |
|---|---|---|
df |
sí |
climasus_df estandarizado (stage
"stand"+) |
create_age_groups |
sí | Crea age_group, grupo_risco_climatico y
faixa_etaria_ibge (predeterminado TRUE) |
age_breaks |
opcional | Cortes de los grupos de edad; predeterminado
c(0, 5, 15, 60, Inf)
|
age_labels |
opcional | Etiquetas de los grupos; si es NULL, generadas a partir
de age_breaks
|
create_calendar_vars |
sí | Crea ano, mes, trimestre,
etc. (predeterminado TRUE) |
create_climate_vars |
opcional | Crea la estación del año; exige
create_calendar_vars = TRUE
|
climate_region |
opcional | Región climática ("norte", "nordeste",
"centro-oeste", "sudeste",
"sul"); define estación seca/lluviosa |
hemisphere |
opcional |
"south" (predeterminado, Brasil) o
"north"
|
age_col / date_col
|
opcional | Fuerzan la columna de edad/fecha; si es NULL,
autodetecta |
backend |
opcional |
"arrow" (lazy, predeterminado) o
"tibble"
|
lang / verbose
|
opcional | Idioma ("pt"/"en"/"es") y
mensajes |
Retorno: el climasus_df con las nuevas
columnas y el stage avanzado a "derive". La edad se
determina mediante una jerarquía: (1) columna de edad existente, (2)
cálculo a partir de la fecha de nacimiento y la fecha del evento
(estándar de referencia), (3) decodificación del código de edad del
DATASUS (alternativa).
sus_data_aggregate()
Agrega microdatos individuales en una serie temporal de conteos.
Requiere el stage "stand" (o posterior).
| Argumento | ¿Esencial? | Descripción |
|---|---|---|
df |
sí |
climasus_df (salida de
estandarización/filtrado/derivación) |
time_unit |
sí |
"day", "week", "month",
"quarter", "year", "season", o
múltiplos como "5 days", "14 days",
"3 months" (predeterminado "day") |
fun |
opcional |
"count" (predeterminado), "sum",
"mean", "median", "min",
"max", "sd", "q25",
"q75", "q95", "q99", o lista con
nombres |
group_by |
opcional | Columnas de estratificación (p. ej.,
c("age_group", "sexo")); NULL agrega en el
municipio detectado |
value_col |
solo si fun != "count"
|
Columna numérica a agregar |
complete_dates |
recomendado |
TRUE rellena los períodos sin evento con cero
(predeterminado FALSE) |
date_col |
opcional | Columna de fecha; si es NULL, autodetecta según el
sistema |
backend |
opcional |
"arrow" (lazy, predeterminado) o
"tibble"
|
lang / verbose
|
opcional | Idioma y mensajes |
Retorno: un climasus_df en el stage
"aggregate" con una columna date (inicio del
período), las columnas de group_by y la columna de conteo
nombrada de forma inteligente según el sistema:
n_obitos (SIM), n_internacoes (SIH),
n_nascimentos (SINASC), n_casos (SINAN),
n_procedimentos (SIA), n_estabelecimentos
(CNES).
sus_data_plot_aggregate_ts()
Gráficos de serie temporal a partir de un climasus_df en
el stage "aggregate".
| Argumento | Descripción |
|---|---|
df |
climasus_df agregado |
value_col |
Columna del desenlace; si es NULL, autodetecta
(n_obitos, n_casos, …) |
plot_type |
"epidemic", "seasonal",
"heatmap", "trend" (acepta varios, vía
patchwork) |
group_col / facet_col
|
Columna para el color (epidemic/seasonal) y para los paneles
(facet_wrap) |
smooth_method / smooth_span
|
Suavizado de la curva epidémica: "loess"
(predeterminado), "gam", "lm",
"none"
|
log_transform |
Aplica log1p en el eje y / relleno |
palette |
"lancet" (predeterminado), "nejm",
"jco", "uchicago", "viridis"
|
city |
Filtra municipios (nombre o código IBGE) antes de graficar |
interactive |
TRUE retorna un widget plotly
|
lang / verbose
|
Idioma y mensajes |
Retorno: el objeto ggplot2 (o
plotly si interactive = TRUE), de forma
invisible; también imprime el gráfico. No altera el stage de
df.
sus_data_plot_aggregate_map()
Mapa municipal de los conteos agregados.
| Argumento | Descripción |
|---|---|
df |
climasus_df agregado con columna de código
municipal |
value_col |
Columna del desenlace; si es NULL, autodetecta |
map_type |
"bubble" (predeterminado, sin
geobr/sf), "choropleth",
"quantile_choropleth"
|
rate_per_100k |
TRUE calcula la incidencia por 100.000 habitantes (usa
pop_25) |
period |
Date o c(inicio, fin) para filtrar antes
de agregar |
city / top_n
|
Restringe a municipios; etiqueta los top_n mayores |
state_borders |
Superpone fronteras estatales (vía geobr) |
palette |
Paleta RColorBrewer ("YlOrRd",
"Blues", …) o
"lancet"/"nejm"
|
log_scale |
log1p en la escala de color (predeterminado
TRUE) |
interactive |
TRUE retorna plotly
|
use_cache / cache_dir
|
Caché de los metadatos municipales |
lang / verbose
|
Idioma y mensajes |
Retorno: un objeto ggplot2 (o
plotly). El coroplético exige los paquetes
Suggests geobr y sf; si están
ausentes, la función recurre al mapa de burbujas con una advertencia.
No modifica df ni avanza el stage.
Fórmulas
El conteo agregado de un desenlace en el período
(con fun = "count") es simplemente el número de registros
cuya fecha cae en ese período:
donde
es la fecha del evento
,
redondea al inicio del período en la unidad
(time_unit), y
es la función indicadora.
La figura de tendencia anual
(plot_type = "trend") reporta la variación porcentual año a
año (YoY):
Cuando rate_per_100k = TRUE en el mapa, la tasa
de incidencia por municipio es
Resultados ilustrados

Figura 1. Curva epidémica diaria de muertes
respiratorias en adultos mayores (60+) en la Región Metropolitana de São
Paulo, 2014–2019, generada por
sus_data_plot_aggregate_ts(plot_type = "epidemic"). El área
y la línea muestran el conteo diario; la curva suavizada (loess) destaca
la tendencia de fondo.

Figura 2. Distribución estacional mensual
(sus_data_plot_aggregate_ts(plot_type = "seasonal")). Los
boxplots por mes evidencian la estacionalidad invernal (junio–agosto) de
la mortalidad respiratoria de adultos mayores — el punto de partida de
la hipótesis clima–salud del caso conductor.

Figura 3. Serie mensual estratificada por los grupos
de edad creados en sus_data_create_variables() (60–69,
70–79, 80+). Es esta estructura estratificada la que se guarda en
caso_serie.rds para los próximos tutoriales.

Figura 4. Distribución espacial de las muertes por
municipio
(sus_data_plot_aggregate_map(map_type = "bubble")). El
tamaño y el color de las burbujas codifican el total de eventos por
municipio de la Región Metropolitana de São Paulo (escala
log1p).
| data_obito | idade | age_years | age_group | grupo_risco_climatico | faixa_etaria_ibge | ano | mes | trimestre | estacao_climatica | estacao_seca_chuvosa |
|---|---|---|---|---|---|---|---|---|---|---|
| 2018-05-21 | 85 | 85 | 80+ | Alto Risco (65+) | 80+ | 2018 | 5 | 2 | Seca | Seca |
| 2015-12-01 | 86 | 86 | 80+ | Alto Risco (65+) | 80+ | 2015 | 12 | 4 | Chuvosa | Chuvosa |
| 2016-07-01 | 78 | 78 | 70-79 | Alto Risco (65+) | 75-79 | 2016 | 7 | 3 | Seca | Seca |
| 2014-04-15 | 75 | 75 | 70-79 | Alto Risco (65+) | 75-79 | 2014 | 4 | 2 | Seca | Seca |
| 2016-08-19 | 63 | 63 | 60-69 | Risco Padrao (5-64) | 60-64 | 2016 | 8 | 3 | Seca | Seca |
| 2016-11-18 | 82 | 82 | 80+ | Alto Risco (65+) | 80+ | 2016 | 11 | 4 | Chuvosa | Chuvosa |
| 2018-06-28 | 93 | 93 | 80+ | Alto Risco (65+) | 80+ | 2018 | 6 | 2 | Seca | Seca |
| 2015-02-02 | 84 | 84 | 80+ | Alto Risco (65+) | 80+ | 2015 | 2 | 1 | Chuvosa | Chuvosa |
| 2014-07-22 | 85 | 85 | 80+ | Alto Risco (65+) | 80+ | 2014 | 7 | 3 | Seca | Seca |
| 2017-10-16 | 61 | 61 | 60-69 | Risco Padrao (5-64) | 60-64 | 2017 | 10 | 4 | Chuvosa | Chuvosa |
| Serie | Unidade_temporal | N_periodos | Total_eventos | Inicio | Fim |
|---|---|---|---|---|---|
| Diaria (todos os obitos) | dia | 2191 | 6000 | 2014-01-01 | 2019-12-31 |
| Mensal (por faixa etaria) | mes | 72 | 6000 | 2014-01-01 | 2019-12-01 |
Referencias
- Bhaskaran, K., Gasparrini, A., Hajat, S., Smeeth, L., & Armstrong, B. (2013). Time series regression studies in environmental epidemiology. International Journal of Epidemiology, 42(4), 1187–1195.
- Gasparrini, A., Guo, Y., Hashizume, M., Lavigne, E., Zanobetti, A., Schwartz, J., et al. (2015). Mortality risk attributable to high and low ambient temperature: a multicountry observational study. The Lancet, 386(9991), 369–375.
- Instituto Brasileiro de Geografia e Estatística (IBGE). (2010). Censo Demográfico 2010. Rio de Janeiro: IBGE.
- World Health Organization (WHO). (2014). Quantitative risk assessment of the effects of climate change on selected causes of death, 2030s and 2050s. Geneva: WHO.