--- title: "Diseños de encuestas y validación (ES)" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Diseños de encuestas y validación (ES)} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", warning = FALSE, message = FALSE ) ``` ## Introducción Los diseños muestrales complejos requieren un tratamiento especial para la estimación correcta de la varianza. metasurvey gestiona el diseño muestral de forma automática mediante el objeto `Survey`, de modo que el usuario pueda concentrarse en el análisis y no en los detalles técnicos. Esta viñeta aborda los siguientes temas: 1. Creación de encuestas con distintos tipos de diseño 2. Configuración de ponderadores y motores de datos 3. Validación del pipeline de procesamiento 4. Verificación cruzada de resultados con el paquete `survey` ## Configuración inicial Utilizamos el conjunto de datos Academic Performance Index (API) del paquete `survey`. Incluye versiones estratificadas, por conglomerados y de muestreo aleatorio simple. ```{r setup} library(metasurvey.core) library(survey) library(data.table) data(api, package = "survey") dt_strat <- data.table(apistrat) ``` ## Tipos de diseño muestral ### Diseño ponderado simple El diseño más sencillo utiliza ponderadores de probabilidad sin conglomerados ni estratificación: ```{r simple} svy_simple <- Survey$new( data = dt_strat, edition = "2000", type = "api", psu = NULL, engine = "data.table", weight = add_weight(annual = "pw") ) cat_design(svy_simple) ``` ### Diseño estratificado por conglomerados Muchas encuestas nacionales utilizan muestreo estratificado multietápico. Se pasan `strata` y `psu` a `Survey$new()`: ```{r stratified} dt_clus <- data.table(apiclus1) svy_strat_clus <- Survey$new( data = dt_strat, edition = "2000", type = "api", psu = NULL, strata = "stype", engine = "data.table", weight = add_weight(annual = "pw") ) cat_design(svy_strat_clus) ``` Validación cruzada con el paquete `survey`: ```{r stratified-validate} design_strat <- svydesign( id = ~1, strata = ~stype, weights = ~pw, data = dt_strat ) direct_strat <- svymean(~api00, design_strat) wf_strat <- workflow( list(svy_strat_clus), survey::svymean(~api00, na.rm = TRUE), estimation_type = "annual" ) cat("Direct estimate:", round(coef(direct_strat), 2), "\n") cat("Workflow estimate:", round(wf_strat$value, 2), "\n") cat("Match:", all.equal( as.numeric(coef(direct_strat)), wf_strat$value, tolerance = 1e-6 ), "\n") ``` Para ejemplos reales de diseños estratificados por conglomerados con datos de CASEN, PNADc, ENIGH y DHS, ver el [artículo de encuestas internacionales](international-surveys-es.html). ### Inspección del diseño ```{r inspect-design} # Check design type cat_design_type(svy_simple, "annual") # View metadata get_metadata(svy_simple) ``` ### Múltiples tipos de ponderadores Muchas encuestas proporcionan distintos ponderadores según el período de análisis (por ejemplo, anual vs. mensual). metasurvey asocia etiquetas de periodicidad a columnas de ponderadores: ```{r multi-weight} set.seed(42) dt_multi <- copy(dt_strat) dt_multi[, pw_monthly := pw * runif(.N, 0.9, 1.1)] svy_multi <- Survey$new( data = dt_multi, edition = "2000", type = "api", psu = NULL, engine = "data.table", weight = add_weight(annual = "pw", monthly = "pw_monthly") ) # Use different weight types in workflow() annual_est <- workflow( list(svy_multi), survey::svymean(~api00, na.rm = TRUE), estimation_type = "annual" ) monthly_est <- workflow( list(svy_multi), survey::svymean(~api00, na.rm = TRUE), estimation_type = "monthly" ) cat("Annual estimate:", round(annual_est$value, 1), "\n") cat("Monthly estimate:", round(monthly_est$value, 1), "\n") ``` ### Ponderadores de réplicas bootstrap Para encuestas que proporcionan réplicas bootstrap (como la ECH de Uruguay), se utiliza `add_replicate()` dentro de `add_weight()`: ```r # This example requires external files svy_boot <- load_survey( path = "data/main_survey.csv", svy_type = "ech", svy_edition = "2023", svy_weight = add_weight( annual = add_replicate( weight_var = "pesoano", replicate_path = "data/bootstrap_replicates.csv", replicate_id = c("numero" = "id"), replicate_pattern = "bsrep[0-9]+", replicate_type = "bootstrap" ) ) ) ``` Cuando se configuran ponderadores de réplicas, `workflow()` los utiliza automáticamente para la estimación de varianza mediante `survey::svrepdesign()`. ## Configuración del motor y el procesamiento ### Motor de datos metasurvey utiliza `data.table` por defecto para una manipulación rápida de los datos: ```{r engine} # Current engine get_engine() # Available engines show_engines() ``` ### Ejecución de steps y procesamiento diferido `step_compute()`, `step_recode()` y `step_join()` se ejecutan de forma eager al crearse; `step_filter()` y `step_validate()` quedan siempre diferidos hasta `bake_steps()`, porque el filtrado afecta el diseño muestral. La configuración de procesamiento diferido solo controla `step_rename()` y `step_remove()` (diferidos por defecto): ```{r lazy} # Check current setting (applies to rename/remove only) lazy_default() # Change for the session (not recommended for most workflows) # set_lazy_processing(FALSE) ``` ### Comportamiento de copia Se puede controlar si las operaciones de steps modifican los datos in-place o trabajan sobre copias: ```{r copy} # Current setting use_copy_default() # In-place is faster but modifies the original # set_use_copy(FALSE) ``` ## Estimación de varianza ### Varianza basada en el diseño Estimación estándar de la varianza a partir del diseño muestral: ```{r variance} results <- workflow( list(svy_simple), survey::svymean(~api00, na.rm = TRUE), survey::svytotal(~enroll, na.rm = TRUE), estimation_type = "annual" ) results ``` ### Estimación por dominios Se pueden calcular estimaciones para subpoblaciones con `survey::svyby()`: ```{r domain} domain_results <- workflow( list(svy_simple), survey::svyby(~api00, ~stype, survey::svymean, na.rm = TRUE), estimation_type = "annual" ) domain_results ``` ### Razones ```{r ratio} ratio_result <- workflow( list(svy_simple), survey::svyratio(~api00, ~api99), estimation_type = "annual" ) ratio_result ``` ## Validación del pipeline ### Verificación paso a paso Al construir pipelines complejos, conviene verificar cada paso de forma independiente: ```{r validate-steps} # Step 1: Compute new variable svy_v <- step_compute(svy_simple, api_diff = api00 - api99, comment = "API score difference" ) # The compute already executed; the step is recorded in the pipeline steps <- get_steps(svy_v) cat("Recorded steps:", length(steps), "\n") ``` ### Validación cruzada con el paquete survey Se pueden comparar los resultados de `workflow()` de metasurvey con llamadas directas al paquete `survey`: ```{r cross-validate} # Method 1: Direct survey package design <- svydesign(id = ~1, weights = ~pw, data = dt_strat) direct_mean <- svymean(~api00, design) # Method 2: metasurvey workflow wf_result <- workflow( list(svy_simple), survey::svymean(~api00, na.rm = TRUE), estimation_type = "annual" ) cat("Direct estimate:", round(coef(direct_mean), 2), "\n") cat("Workflow estimate:", round(wf_result$value, 2), "\n") cat("Match:", all.equal( as.numeric(coef(direct_mean)), wf_result$value, tolerance = 1e-6 ), "\n") ``` ### Visualización del pipeline Con `view_graph()` se puede visualizar el grafo de dependencias entre steps: ```{r view-graph, eval = requireNamespace("visNetwork", quietly = TRUE)} # Requires the visNetwork package svy_viz <- step_compute(svy_simple, api_diff = api00 - api99, high_growth = as.integer(api00 - api99 > 50) ) view_graph(svy_viz, init_step = "Load API data") ``` El DAG interactivo no se renderiza en esta vignette para reducir el tamaño del paquete; puede explorarse ejecutando el código anterior en una sesión interactiva de R. ### Evaluación de calidad Se puede evaluar la calidad de las estimaciones a partir del coeficiente de variación: ```{r cv-check} results_quality <- workflow( list(svy_simple), survey::svymean(~api00, na.rm = TRUE), survey::svymean(~enroll, na.rm = TRUE), estimation_type = "annual" ) for (i in seq_len(nrow(results_quality))) { cv_pct <- results_quality$cv[i] * 100 cat( results_quality$stat[i], ":", round(cv_pct, 1), "% CV -", evaluate_cv(cv_pct), "\n" ) } ``` ### Validación de recipes Se puede verificar que los recipes y sus steps sean consistentes: ```{r roundtrip} # Create steps and recipe svy_rt <- step_compute(svy_simple, api_diff = api00 - api99) my_recipe <- steps_to_recipe( name = "API Test", user = "QA Team", svy = svy_rt, description = "Recipe for validation", steps = get_steps(svy_rt) ) # Check documentation is correct doc <- my_recipe$doc() cat("Input variables:", toString(doc$input_variables), "\n") cat("Output variables:", toString(doc$output_variables), "\n") # Validate against the survey my_recipe$validate(svy_rt) ``` ## Lista de verificación para validación Antes de poner en producción un pipeline de procesamiento de encuestas, se recomienda verificar lo siguiente: 1. **Integridad de los datos** -- cantidad de filas, nombres de columnas y tipos de datos después de cada step 2. **Validación de ponderadores** -- las columnas de ponderadores existen y son positivas 3. **Verificación del diseño** -- el diseño muestral coincide con la especificación esperada (PSU, estratos, ponderadores) 4. **Reproducibilidad del recipe** -- guardar y recargar recipes, verificar el round-trip en JSON 5. **Validación cruzada** -- comparar estimaciones clave con valores publicados o llamadas directas al paquete `survey` 6. **Umbrales de CV** -- señalar estimaciones con coeficientes de variación elevados ```{r checklist} validate_pipeline <- function(svy) { data <- get_data(svy) checks <- list( has_data = !is.null(data), has_rows = nrow(data) > 0, has_weights = all( unlist(svy$weight)[is.character(unlist(svy$weight))] %in% names(data) ) ) passed <- all(unlist(checks)) if (passed) { message("All validation checks passed") } else { failed <- names(checks)[!unlist(checks)] warning("Failed checks: ", toString(failed)) } invisible(checks) } validate_pipeline(svy_simple) ``` ## Buenas prácticas 1. **Utilizar siempre los ponderadores adecuados** -- nunca calcular estadísticos sin ponderar a partir de datos de encuestas 2. **Usar ponderadores de réplicas cuando estén disponibles** -- proporcionan estimaciones de varianza más robustas 3. **Verificar los tamaños de muestra por dominio** -- combinar dominios pequeños cuando los CV sean demasiado altos 4. **Documentar el diseño** -- incluir la especificación del diseño, la construcción de los ponderadores y el método de varianza 5. **Hacer validación cruzada de las estimaciones clave** -- comparar con valores publicados o métodos alternativos ## Próximos pasos - **[Flujos de estimación](workflows-and-estimation-es.html)** -- `workflow()`, `RecipeWorkflow` y estimaciones publicables - **[Paneles rotativos y PoolSurvey](panel-analysis-es.html)** -- Análisis longitudinal con `RotativePanelSurvey` y `PoolSurvey`