Introduccion
Trabajar con microdatos de encuestas de hogares implica una gran cantidad de procesamiento repetitivo: recodificar variables categoricas, construir indicadores, unir datos externos y calcular estimaciones ponderadas. Cada investigador escribe su propia version de estas transformaciones, y el codigo rara vez se comparte o documenta de forma que otros puedan reutilizarlo.
metasurvey aborda este problema proporcionando una
capa de metaprogramacion sobre el paquete survey (Lumley 2004). En
lugar de escribir scripts ad hoc, se construye un
pipeline de transformaciones que es:
- Documentado – cada paso lleva un comentario, sus variables de entrada/salida y sus dependencias
- Reproducible – el pipeline puede guardarse como una receta y aplicarse a nuevos datos
- Compartible – las recetas pueden publicarse en una API publica donde otros investigadores pueden descubrirlas y reutilizarlas
El pipeline tiene tres niveles:
- Steps – transformaciones individuales (compute, recode, filter, rename, remove, join, validate)
- Recipes – colecciones reutilizables de steps agrupados con metadatos
-
Workflows – estimaciones estadisticas
(
svymean,svytotal,svyby) que producen las tablas finales
El paquete maneja el survey design —estratificacion, conglomerados,
pesos replicados— automaticamente a traves del objeto
Survey. El usuario se enfoca en el analisis sustantivo;
metasurvey se encarga de la infraestructura.
Creacion de un objeto Survey
Un objeto Survey agrupa los microdatos con metadatos
sobre pesos, edicion y tipo de encuesta. Utilizamos una muestra de
microdatos reales de la Encuesta Continua de Hogares (ECH)
2023, publicada por el Instituto Nacional de Estadistica (INE) de
Uruguay.
La ECH es una encuesta de hogares de panel rotativo. Las variables clave incluyen:
- e27: Edad en anios
- e26: Sexo (1 = Hombre, 2 = Mujer)
- e30: Parentesco con el jefe de hogar (1-14)
-
POBPCOAC: Condicion de actividad
- 1 = Menor de 14
- 2 = Ocupado
- 3-5 = Desocupado
- 6-10 = Inactivo
- 11 = No aplica
- HT11: Ingreso del hogar (pesos uruguayos)
- W_ANO: Factor de expansion anual (peso)
library(metasurvey)
library(data.table)
# Cargar muestra de microdatos reales de la ECH 2023 (200 hogares, ~500 personas)
dt <- fread(system.file("extdata", "ech_2023_sample.csv", package = "metasurvey"))
# Crear objeto Survey
svy <- Survey$new(
data = dt,
edition = "2023",
type = "ech",
engine = "data.table",
weight = add_weight(annual = "W_ANO")
)La funcion add_weight() mapea etiquetas de periodicidad
(por ejemplo, “annual”, “monthly”) a los nombres de las columnas de
pesos en los datos. Esto permite que la misma receta funcione con
distintas ediciones de la encuesta.
Es posible inspeccionar los datos en cualquier momento:
head(get_data(svy), 3)
#> ID nper anio mes region dpto nom_dpto e26 e27 e30 e51_2
#> <int> <int> <int> <int> <int> <int> <char> <int> <int> <int> <int>
#> 1: 34561 1 2023 1 1 1 Montevideo 2 26 1 6
#> 2: 34561 2 2023 1 1 1 Montevideo 2 45 7 6
#> 3: 34561 3 2023 1 1 1 Montevideo 2 7 4 1
#> POBPCOAC SUBEMPLEO HT11 pobre06 W_ANO
#> <int> <int> <num> <int> <int>
#> 1: 2 0 55429.6 0 57
#> 2: 4 0 55429.6 0 57
#> 3: 1 0 55429.6 0 57Trabajo con Steps
Los steps son lazy por defecto: se registran pero no
se ejecutan hasta que se llama a bake_steps(). Esto
permite:
- Construir un pipeline de transformacion completo
- Inspeccionar y validar los steps antes de la ejecucion
- Reutilizar secuencias de steps como recetas
- Asegurar que todas las dependencias existan antes del procesamiento
Calculo de nuevas variables
Se utiliza step_compute() para crear variables
derivadas. El paquete automaticamente:
- Valida que las variables de entrada existan
- Detecta dependencias entre steps
- Optimiza las expresiones para mejorar el rendimiento
svy <- step_compute(svy,
# Convert income to thousands for readability
ht11_thousands = HT11 / 1000,
# Create employment indicator following ILO definitions
employed = ifelse(POBPCOAC == 2, 1, 0),
# Working age population (14+ years, ECH standard)
working_age = ifelse(e27 >= 14, 1, 0),
comment = "Basic labor force indicators"
)Es posible agrupar calculos usando el parametro .by
(similar a data.table):
# Calculate mean household income per department
svy <- step_compute(svy,
mean_income_dept = mean(HT11, na.rm = TRUE),
.by = "dpto",
comment = "Department-level income averages"
)Recodificacion en categorias
Se utiliza step_recode() para crear variables
categoricas a partir de condiciones. Las condiciones se evaluan
de arriba hacia abajo, y la primera coincidencia es la
que se aplica.
# Recode labor force status (POBPCOAC) into meaningful categories
svy <- step_recode(svy, labor_status,
POBPCOAC == 2 ~ "Employed",
POBPCOAC %in% 3:5 ~ "Unemployed",
POBPCOAC %in% 6:10 ~ "Inactive",
.default = "Not classified",
comment = "Labor force status - ILO standard"
)
# Create standard age groups for labor statistics
svy <- step_recode(svy, age_group,
e27 < 25 ~ "Youth (14-24)",
e27 < 45 ~ "Adult (25-44)",
e27 < 65 ~ "Mature (45-64)",
.default = "Elderly (65+)",
.to_factor = TRUE, # Convert to factor
ordered = TRUE, # Ordered factor
comment = "Age groups for labor analysis"
)
# Recode sex into descriptive labels
svy <- step_recode(svy, gender,
e26 == 1 ~ "Male",
e26 == 2 ~ "Female",
.default = "Other",
comment = "Gender classification"
)Filtrado de filas
Se utiliza step_filter() para seleccionar filas segun
condiciones logicas. Multiples condiciones se combinan con AND. Al igual
que los demas steps, los filtros son lazy por defecto.
# Mantener solo individuos en edad de trabajar (14+)
svy <- step_filter(svy,
e27 >= 14,
comment = "Working-age population only"
)Renombrar y eliminar variables
Se renombran variables para mayor claridad o consistencia:
svy <- step_rename(svy,
age = e27, # Rename e27 to age
sex_code = e26 # Keep original as sex_code
)Se eliminan variables que ya no son necesarias:
# Remove intermediate calculations
svy <- step_remove(svy, working_age, mean_income_dept)Union con datos externos
Se utiliza step_join() para unir datos de referencia
externos. Esto es util para agregar:
- Nombres y clasificaciones geograficas
- Tipos de cambio o deflactores
- Benchmarks o metas externas
Los microdatos reales de la ECH ya incluyen nom_dpto y
region. Aqui demostramos un join con lineas de pobreza como
ejemplo:
# Lineas de pobreza por region (valores ilustrativos en UYU, 2023)
poverty_lines <- data.table(
region = 1:3,
poverty_line = c(19000, 12500, 11000),
region_name = c("Montevideo", "Interior loc. >= 5000", "Interior loc. < 5000")
)
svy <- step_join(svy,
poverty_lines,
by = "region",
type = "left",
comment = "Add poverty lines by region"
)Ejecucion de transformaciones
Aplicacion de steps (bake)
Se llama a bake_steps() para ejecutar todas las
transformaciones pendientes:
svy <- bake_steps(svy)
head(get_data(svy), 3)
#> region dpto ID nper anio mes nom_dpto sex_code age e30 e51_2
#> <int> <int> <int> <int> <int> <int> <char> <int> <int> <int> <int>
#> 1: 1 1 34561 1 2023 1 Montevideo 2 26 1 6
#> 2: 1 1 34561 2 2023 1 Montevideo 2 45 7 6
#> 3: 1 1 34678 1 2023 1 Montevideo 1 48 1 6
#> POBPCOAC SUBEMPLEO HT11 pobre06 W_ANO ht11_thousands employed
#> <int> <int> <num> <int> <int> <num> <num>
#> 1: 2 0 55429.6 0 57 55.4296 1
#> 2: 4 0 55429.6 0 57 55.4296 0
#> 3: 2 0 152958.8 0 54 152.9588 1
#> labor_status age_group gender poverty_line region_name poverty_line.y
#> <char> <fctr> <char> <num> <char> <num>
#> 1: Employed Mature (45-64) Female 19000 Montevideo 19000
#> 2: Unemployed Mature (45-64) Female 19000 Montevideo 19000
#> 3: Employed Mature (45-64) Male 19000 Montevideo 19000
#> region_name.y
#> <char>
#> 1: Montevideo
#> 2: Montevideo
#> 3: MontevideoEl historial de steps se preserva para documentacion y reproducibilidad:
Visualizacion del pipeline
Es posible visualizar el pipeline de transformacion como un grafo dirigido:
view_graph(svy, init_step = "Load ECH 2023")Esto genera un grafo interactivo que muestra:
- Fuentes de datos y uniones
- Steps de transformacion
- Dependencias entre variables
- Comentarios y metadatos
Estimaciones estadisticas
Una vez preparados los datos, se utiliza workflow() para
calcular estimaciones de encuesta. La funcion envuelve los estimadores
del paquete survey (Lumley 2004) y devuelve resultados
ordenados con errores estandar y coeficientes de variacion.
Importante: Se debe pasar el objeto survey dentro de
un list().
Estimaciones basicas
# Estimate mean household income
result <- workflow(
list(svy),
survey::svymean(~HT11, na.rm = TRUE),
estimation_type = "annual"
)
result
#> stat value se cv confint_lower
#> <char> <num> <num> <num> <num>
#> 1: survey::svymean: HT11 110389.3 4076.154 0.03692528 102400.1
#> confint_upper
#> <num>
#> 1: 118378.4La salida incluye:
-
estimate: Estimacion puntual -
se: Error estandar -
cv: Coeficiente de variacion -
var_name: Nombre de la variable -
level: Nivel del factor (para variables categoricas)
Estimaciones multiples
Es posible calcular varias estadisticas en una sola llamada:
results <- workflow(
list(svy),
survey::svymean(~HT11, na.rm = TRUE), # Mean income
survey::svytotal(~employed, na.rm = TRUE), # Total employed
survey::svymean(~labor_status, na.rm = TRUE), # Employment distribution
estimation_type = "annual"
)
results
#> stat value se cv
#> <char> <num> <num> <num>
#> 1: survey::svymean: HT11 1.103893e+05 4.076154e+03 0.03692528
#> 2: survey::svytotal: employed 1.426200e+04 6.756206e+02 0.04737208
#> 3: survey::svymean: labor_statusEmployed 5.551576e-01 2.610113e-02 0.04701571
#> 4: survey::svymean: labor_statusInactive 3.860646e-01 2.551750e-02 0.06609646
#> 5: survey::svymean: labor_statusUnemployed 5.877773e-02 1.309115e-02 0.22272291
#> confint_lower confint_upper
#> <num> <num>
#> 1: 1.024001e+05 1.183784e+05
#> 2: 1.293781e+04 1.558619e+04
#> 3: 5.040004e-01 6.063149e-01
#> 4: 3.360512e-01 4.360780e-01
#> 5: 3.311956e-02 8.443591e-02Estimacion por dominios
Se calculan estimaciones para subpoblaciones usando
survey::svyby():
# Mean income by gender
income_by_gender <- workflow(
list(svy),
survey::svyby(~HT11, ~gender, survey::svymean, na.rm = TRUE),
estimation_type = "annual"
)
income_by_gender
#> stat value se cv
#> <char> <num> <num> <num>
#> 1: survey::svyby: HT11 [gender=Female] 111107.9 5955.676 0.05360263
#> 2: survey::svyby: HT11 [gender=Male] 109608.9 5519.291 0.05035439
#> confint_lower confint_upper gender
#> <num> <num> <char>
#> 1: 99434.99 122780.8 Female
#> 2: 98791.31 120426.5 MaleEvaluacion de calidad
El coeficiente de variacion (CV) mide la confiabilidad de las estimaciones. Un CV mas bajo indica estimaciones mas precisas. Siguiendo las pautas del INE Uruguay (Instituto Nacional de Estadística (INE) 2023):
| Rango de CV | Categoria de calidad | Recomendacion |
|---|---|---|
| < 5% | Excelente | Usar sin restricciones |
| 5%–10% | Muy buena | Usar con confianza |
| 10%–15% | Buena | Usar para la mayoria de los propositos |
| 15%–25% | Aceptable | Usar con precaucion, senialando limitaciones |
| 25%–35% | Pobre | Usar solo para tendencias generales |
| >= 35% | No confiable | No publicar |
Se utiliza evaluate_cv() para clasificar la calidad de
las estimaciones:
# Check quality of mean income estimate
cv_percentage <- results$cv[1] * 100
quality <- evaluate_cv(cv_percentage)
cat("CV:", round(cv_percentage, 2), "%\n")
#> CV: 3.69 %
cat("Quality:", quality, "\n")
#> Quality: ExcellentPara estadisticas oficiales, siempre se debe reportar:
- Estimacion puntual
- Error estandar o intervalo de confianza
- Coeficiente de variacion
- Clasificacion de calidad
- Tamanio de la muestra
Trabajo con Recipes
Las recipes agrupan steps de transformacion para reproducibilidad y comparticion. Una vez desarrollado un pipeline funcional, se puede convertir en una receta que puede ser:
- Aplicada a diferentes ediciones de la encuesta
- Compartida con colaboradores
- Publicada para garantizar transparencia
- Versionada y documentada
Creacion de una Recipe
Se crea una receta a partir de los steps desarrollados:
# Convert current steps to a recipe
labor_recipe <- steps_to_recipe(
name = "ECH Labor Force Indicators",
user = "National Statistics Office",
svy = svy,
description = paste(
"Standard labor force indicators following ILO definitions.",
"Creates employment status, age groups, and gender classifications."
),
steps = get_steps(svy),
topic = "labor_statistics"
)
class(labor_recipe)
#> [1] "Recipe" "R6"
labor_recipe$name
#> [1] "ECH Labor Force Indicators"O se puede definir una receta desde cero:
minimal_recipe <- recipe(
name = "Basic Demographics - ECH",
user = "analyst",
svy = survey_empty(type = "ech", edition = "2023"),
description = "Basic demographic recoding for ECH microdata",
topic = "demographics",
# Define steps inline
step_recode(
gender,
e26 == 1 ~ "Male",
e26 == 2 ~ "Female",
.default = "Other"
),
step_recode(
age_group,
e27 < 14 ~ "Child",
e27 < 65 ~ "Adult",
.default = "Senior"
)
)Aplicacion de Recipes a nuevos datos
Una vez publicada, cualquier persona puede recuperar una receta por ID y aplicarla a sus datos:
# Obtener una receta por ID desde la API (requiere servidor)
r <- api_get_recipe("ech_labor_001")
# Aplicar a una nueva encuesta
new_svy <- add_recipe(new_svy, r)
processed <- bake_recipes(new_svy)Documentacion de Recipes
Las recetas documentan automaticamente sus transformaciones:
doc <- labor_recipe$doc()
names(doc)
#> [1] "meta" "input_variables" "output_variables" "pipeline"
# Input variables required
doc$input_variables
#> [1] "HT11" "POBPCOAC" "e27" "e26" "region"
# Output variables created
doc$output_variables
#> [1] "ht11_thousands" "employed" "working_age" "mean_income_dept"
#> [5] "labor_status" "age_group" "gender" "mapping"Configuracion del paquete
metasurvey ofrece configuraciones globales que se pueden ajustar segun el flujo de trabajo:
# Check current lazy-processing setting
lazy_default() # TRUE = steps recorded but not executed immediately
#> [1] TRUE
# Check data-copy behavior
use_copy_default() # TRUE = operate on copies (safer but slower)
#> [1] TRUE
# View available computation engines
show_engines() # "data.table", "dplyr", etc.
#> [1] "data.table" "tidyverse" "dplyr"Se pueden modificar las configuraciones para la sesion actual:
# Disable lazy evaluation (execute steps immediately)
set_lazy_processing(FALSE)
# Modify inplace (faster, but modifies original data)
set_use_copy(FALSE)
# Reset to defaults
set_lazy_processing(TRUE)
set_use_copy(TRUE)Compartir el trabajo: el ecosistema de recipes
Uno de los objetivos de metasurvey es reducir el esfuerzo duplicado en la comunidad de investigadores que trabajan con encuestas. Si se ha construido un pipeline de procesamiento util, es posible publicarlo para que otros lo encuentren y reutilicen. El paquete se conecta a una API publica donde se almacenan recipes y workflows:
# Buscar recipes existentes (requiere servidor API)
ech_recipes <- api_list_recipes(survey_type = "ech")
length(ech_recipes)
# Buscar algo especifico
labor <- api_list_recipes(search = "labor")
# Para publicar, crear una cuenta primero
api_register("Your Name", "you@example.com", "password")
# Luego publicar
api_publish_recipe(labor_recipe)El ecosistema soporta tres niveles de certificacion (comunitaria, revisada, oficial) y tres tipos de cuenta (individual, miembro institucional, institucion). Las cuentas institucionales requieren aprobacion de un administrador, lo que asegura que las certificaciones tengan respaldo real.
Para mas detalles, consultar Creacion y comparticion de Recipes.
Datos y agradecimientos
Los datos de ejemplo utilizados en esta vinieta provienen de la Encuesta Continua de Hogares (ECH) 2023, publicada por el Instituto Nacional de Estadistica (INE) de Uruguay. Los microdatos completos estan disponibles en INE.
El paquete ech de Gabriela
Mathieu y Richard Detomasi fue una inspiracion importante para
metasurvey. Mientras que ech provee funciones listas para
usar para calcular indicadores socioeconomicos, metasurvey toma un
enfoque diferente: proporciona una capa de metaprogramacion que permite
a los usuarios definir, compartir y reproducir sus propios pipelines de
procesamiento.
Paquetes relacionados
metasurvey es parte de un ecosistema creciente de paquetes de R para el analisis de encuestas de hogares en America Latina:
- ech – Funciones para el calculo de indicadores socioeconomicos con la ECH de Uruguay (Mathieu & Detomasi). Provee funciones listas para usar sobre pobreza, ingresos, educacion e indicadores de empleo.
- eph – Herramientas para trabajar con la Encuesta Permanente de Hogares de Argentina. Publicado en rOpenSci. Cubre descarga de datos, construccion de paneles y calculo de pobreza.
- survey – El paquete fundamental para inferencia basada en disenio con encuestas complejas (Lumley 2004). metasurvey se construye sobre el.
Proximos pasos
Ahora que se comprenden los conceptos basicos, se pueden explorar estas guias:
- Creacion y comparticion de Recipes – Registro de recipes, certificacion y descubrimiento
-
Workflows de
estimacion –
workflow(),RecipeWorkflowy estimaciones publicables - Survey designs y validacion – Estratificacion, conglomerados, pesos replicados, validacion del pipeline
-
Paneles rotativos y
PoolSurvey – Analisis longitudinal con
RotativePanelSurveyyPoolSurvey - Caso de estudio ECH – Analisis completo del mercado laboral con comparacion con STATA