Cualquier persona que trabaje con microdatos de encuestas de hogares conoce este patrón: se descargan los archivos sin procesar, se abre el libro de códigos y se pasan días recodificando la situación laboral, armonizando variables de ingreso y construyendo indicadores. Meses después, un colega empieza el mismo proyecto y escribe el mismo código desde cero.
En STATA, los equipos comparten archivos .do, pero estos
están fuertemente acoplados a rutas de archivos y nombres de variables
específicos, y no existe una forma estándar de descubrirlos o
validarlos.
Las Recipes son la respuesta de metasurvey a este problema. Una recipe es una colección portable, documentada y validada de pasos de transformación que puede:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 1. Desarrollar│────▶│ 2. Empaquetar │────▶│ 3. Validar │
│ steps sobre │ │ steps en │ │ contra datos │
│ una encuesta │ │ una recipe │ │ nuevos │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
┌──────────────┐ ┌──────────────┐ │
│ 5. Descubrir │◀────│ 4. Publicar │◀────────────┘
│ y reutilizar │ │ en registro │
│ recipes │ │ o API │
└──────────────┘ └──────────────┘
El punto de partida típico es cargar una encuesta con
load_survey(). Se pueden cargar datos de ejemplo o apuntar
a archivos propios:
library(metasurvey.core)
# Cargar ECH 2022 con datos de ejemplo
ech_2022 <- load_survey(
load_survey_example("ech", "ech_2022"),
svy_type = "ech",
svy_edition = "2022",
svy_weight = add_weight(annual = "pesoano")
)
# O cargar con recipes existentes del registry
ech_2022 <- load_survey(
load_survey_example("ech", "ech_2022"),
svy_type = "ech",
svy_edition = "2022",
svy_weight = add_weight(annual = "pesoano"),
recipes = get_recipe("ech", "2022")
)El flujo de trabajo más común consiste en desarrollar las transformaciones de forma interactiva sobre una encuesta y luego convertir los steps registrados en una recipe.
library(metasurvey.core)
library(data.table)
set.seed(42)
n <- 200
# Simular microdatos de encuesta (sustituto de load_survey)
dt <- data.table(
id = 1:n,
age = sample(18:80, n, replace = TRUE),
sex = sample(c(1, 2), n, replace = TRUE),
income = round(runif(n, 5000, 80000)),
activity = sample(c(2, 3, 5, 6), n,
replace = TRUE,
prob = c(0.55, 0.05, 0.05, 0.35)
),
weight = round(runif(n, 0.5, 3.0), 4)
)
svy <- Survey$new(
data = dt,
edition = "2023",
type = "ech",
psu = NULL,
engine = "data.table",
weight = add_weight(annual = "weight")
)
# Desarrollar transformaciones interactivamente
svy <- step_compute(svy,
income_thousands = income / 1000,
employed = as.integer(activity == 2),
comment = "Escalado de ingreso e indicador de empleo"
)
svy <- step_recode(svy, labor_status,
activity == 2 ~ "Empleado",
activity %in% 3:5 ~ "Desempleado",
activity %in% 6:8 ~ "Inactivo",
.default = "Otro",
comment = "Clasificacion OIT de fuerza laboral"
)
svy <- step_recode(svy, age_group,
age < 25 ~ "Joven",
age < 45 ~ "Adulto",
age < 65 ~ "Maduro",
.default = "Mayor",
comment = "Grupos etarios estandar"
)
# Convertir todos los steps a una recipe
labor_recipe <- steps_to_recipe(
name = "Indicadores de Fuerza Laboral",
user = "Equipo de Investigacion",
svy = svy,
description = "Indicadores estandar de fuerza laboral segun definiciones OIT",
steps = get_steps(svy),
topic = "labor"
)
labor_recipe
#>
#> ── Recipe: Indicadores de Fuerza Laboral ──
#> Author: Equipo de Investigacion
#> Survey: ech / 2023
#> Version: 1.0.0
#> Topic: labor
#> Description: Indicadores estandar de fuerza laboral segun definiciones OIT
#> Certification: community
#>
#> ── Requires (3 variables) ──
#> income, activity, age
#>
#> ── Pipeline (3 steps) ──
#> 1. [compute] -> income_thousands, employed "Escalado de ingreso e indicador de empleo"
#> 2. [recode] -> labor_status "Clasificacion OIT de fuerza laboral"
#> 3. [recode] -> age_group "Grupos etarios estandar"
#>
#> ── Produces (4 variables) ──
#> labor_status [categorical], age_group [categorical], income_thousands [numeric], employed [numeric]Toda recipe puede generar automáticamente su documentación a partir
de sus steps. El método doc() devuelve una lista con las
variables de entrada, las variables de salida y el pipeline paso a
paso:
# ¿Qué variables necesita la recipe?
doc$input_variables
#> [1] "income" "activity" "age"
# ¿Qué variables crea?
doc$output_variables
#> [1] "income_thousands" "employed" "labor_status" "age_group"
# Pipeline paso a paso
doc$pipeline
#> [[1]]
#> [[1]]$index
#> [1] 1
#>
#> [[1]]$type
#> [1] "compute"
#>
#> [[1]]$outputs
#> [1] "income_thousands" "employed"
#>
#> [[1]]$inputs
#> [1] "income" "activity"
#>
#> [[1]]$inferred_type
#> [1] "numeric"
#>
#> [[1]]$comment
#> [1] "Escalado de ingreso e indicador de empleo"
#>
#>
#> [[2]]
#> [[2]]$index
#> [1] 2
#>
#> [[2]]$type
#> [1] "recode"
#>
#> [[2]]$outputs
#> [1] "labor_status"
#>
#> [[2]]$inputs
#> [1] "activity"
#>
#> [[2]]$inferred_type
#> [1] "categorical"
#>
#> [[2]]$comment
#> [1] "Clasificacion OIT de fuerza laboral"
#>
#>
#> [[3]]
#> [[3]]$index
#> [1] 3
#>
#> [[3]]$type
#> [1] "recode"
#>
#> [[3]]$outputs
#> [1] "age_group"
#>
#> [[3]]$inputs
#> [1] "age"
#>
#> [[3]]$inferred_type
#> [1] "categorical"
#>
#> [[3]]$comment
#> [1] "Grupos etarios estandar"Esta documentación se genera automáticamente, sin trabajo manual adicional.
Antes de aplicar una recipe a nuevos datos, es conveniente verificar
que todas las variables requeridas existan. El método
validate() se detiene con un error claro si falta alguna
dependencia:
Se pueden adjuntar una o más recipes a una encuesta y aplicarlas con
bake_recipes():
# Crear una encuesta nueva con la misma estructura (simulando una nueva edición)
set.seed(99)
dt2 <- data.table(
id = 1:100,
age = sample(18:80, 100, replace = TRUE),
sex = sample(c(1, 2), 100, replace = TRUE),
income = round(runif(100, 5000, 80000)),
activity = sample(c(2, 3, 5, 6), 100,
replace = TRUE,
prob = c(0.55, 0.05, 0.05, 0.35)
),
weight = round(runif(100, 0.5, 3.0), 4)
)
svy2 <- Survey$new(
data = dt2, edition = "2024", type = "ech",
psu = NULL, engine = "data.table",
weight = add_weight(annual = "weight")
)
# Adjuntar y aplicar
svy2 <- add_recipe(svy2, labor_recipe)
svy2 <- bake_recipes(svy2)
head(get_data(svy2)[, .(id, income_thousands, labor_status, age_group)], 5)
#> id income_thousands labor_status age_group
#> <int> <num> <char> <char>
#> 1: 1 47.346 Desempleado Mayor
#> 2: 2 28.114 Empleado Maduro
#> 3: 3 43.583 Empleado Maduro
#> 4: 4 13.440 Desempleado Adulto
#> 5: 5 55.638 Empleado MayorLa misma recipe aplicada a una edición diferente produce resultados consistentes. De este modo, metasurvey garantiza la reproducibilidad a lo largo del tiempo.
En la práctica, se puede cargar una encuesta y aplicar recipes publicadas en una sola llamada:
Las categorías ayudan a organizar las recipes por tema:
cats <- default_categories()
vapply(cats, function(c) c$name, character(1))
#> [1] "labor_market" "income" "education" "health" "demographics"
#> [6] "housing"Las categorías se agregan a una recipe con
add_category():
labor_recipe <- add_category(labor_recipe, "labor_market", "Analisis del mercado laboral")
labor_recipe <- add_category(labor_recipe, "income", "Indicadores de ingreso")
labor_recipe
#>
#> ── Recipe: Indicadores de Fuerza Laboral ──
#> Author: Equipo de Investigacion
#> Survey: ech / 2023
#> Version: 1.0.0
#> Topic: labor
#> Description: Indicadores estandar de fuerza laboral segun definiciones OIT
#> Certification: community
#> Categories: labor_market, income
#>
#> ── Requires (3 variables) ──
#> income, activity, age
#>
#> ── Pipeline (3 steps) ──
#> 1. [compute] -> income_thousands, employed "Escalado de ingreso e indicador de empleo"
#> 2. [recode] -> labor_status "Clasificacion OIT de fuerza laboral"
#> 3. [recode] -> age_group "Grupos etarios estandar"
#>
#> ── Produces (4 variables) ──
#> labor_status [categorical], age_group [categorical], income_thousands [numeric], employed [numeric]El sistema de certificación ofrece tres niveles de confianza:
| Nivel | Significado |
|---|---|
community |
Contribución de usuario (por defecto), sin revisión |
reviewed |
Revisada por pares de un equipo reconocido |
official |
Avalada para estadísticas oficiales |
Los niveles de certificación más altos aparecen primero en los resultados de búsqueda e indican que la recipe fue revisada.
El verdadero poder de las recipes radica en compartirlas. Cada recipe que creás puede publicarse en el registry de metasurvey, donde otros investigadores pueden descubrirla, reutilizarla y seguir construyendo a partir de tu trabajo.
metasurvey.core incluye un registry
local (basado en JSON, vía publish_recipe() y
read_recipe()) y funciona completamente offline. El
registry remoto que se describe a continuación lo proveen los paquetes
acompañantes metasurvey.explorer.backend
(las funciones api_*() y configure_api()) y metasurvey.explorer.frontend
(el explorador Shiny); instalalos para correr estos ejemplos.
El flujo recomendado es publicar las recipes en la API pública. Cualquier persona puede explorar recipes sin cuenta; para publicar se necesita registro:
library(metasurvey.explorer.backend)
# Una sola vez: registrarse y autenticarse
api_register("Tu Nombre", "[email protected]", "password")
api_login("[email protected]", "password")
# Publicar tu recipe (tu perfil se adjunta automáticamente)
api_publish_recipe(labor_recipe)Si estás autenticado, api_publish_recipe() adjunta
automáticamente tu perfil de usuario a la recipe. Los demás usuarios ven
quién la publicó, junto con la afiliación institucional y el nivel de
certificación. Esto genera responsabilidad y confianza en las recipes
compartidas.
No se necesita autenticación para explorar y descargar recipes:
La app Shiny (del paquete metasurvey.explorer.frontend)
provee una interfaz visual para explorar recipes y workflows:
El explorador muestra tarjetas de recipes con badges de certificación, conteo de descargas y preview del pipeline. Al hacer clic en una recipe se abre una vista de detalle con el pipeline completo, snippet de código R y links a workflows relacionados.
Las instituciones que trabajan con encuestas confidenciales o de acceso restringido pueden necesitar un registry privado. metasurvey contempla este escenario mediante un backend propio con MongoDB:
# Apuntar a la API privada de tu institución
configure_api("https://tu-institucion.example.com/api")
# A partir de aquí, el flujo es idéntico
api_login("[email protected]", "password")
api_publish_recipe(labor_recipe)
api_list_recipes(survey_type = "ech")Consultá el repositorio metasurvey.worker para ver cómo desplegar la API Plumber con MongoDB en tu propia organización.
"ECH Indicadores de Fuerza Laboral").validate() sobre datos de ejemplo para asegurarse de que
todas las dependencias existan.set_version() al actualizarlas.workflow() para calcular
estimaciones ponderadas a partir de los datos procesados