4  Metodología y desarrollo

En este capítulo se divide en dos partes, la primera parte se centra en la metodología de los métodos de estimación de los errores estándar (SE), donde se describen los diferentes métodos de replicas de los pesos muestrales y se explican las ventajas del uso de los pesos replicados. La segunda parte se centra en el desarrollo e implementación de las diferentes partes del paquete. Los ejemplos de código se muestran con código real del paquete metasurvey y donde allí se explican las diferentes partes del código y su funcionamiento intentando ser lo más expositivo posible para que el lector pueda entender el funcionamiento de la meta-programación aunque estos no sean los ejemplos más complejos que se encuentran en el paquete.

4.1 Desarrollo e Implementación

El desarrollo de metasurvey se fundamenta en tres pilares principales: una gestión eficiente de dependencias, una arquitectura modular basada en clases, y el uso de técnicas avanzadas de meta-programación. A continuación, se detalla cada uno de estos aspectos.

4.1.1 Gestión de Dependencias

El diseño de metasurvey prioriza la eficiencia y minimalismo en sus dependencias externas. El núcleo del paquete se apoya en survey para el procesamiento de encuestas complejas, data.table para la manipulación eficiente de datos mediante referencias, y R6 para la implementación orientada a objetos. Para mejorar la legibilidad del código se utiliza glue, mientras que jsonlite y httr facilitan la comunicación con la API. Esta selección cuidadosa contrasta con versiones anteriores que incluían dependencias más pesadas como son tidyverse y rlang, priorizando ahora la eficiencia y ligereza del paquete.

4.1.2 Arquitectura y Diseño de Clases

El paquete utiliza una arquitectura orientada a objetos mediante R6, implementando las siguientes clases principales:

  1. Clase Survey
    • Almacena la encuesta, metadatos y diseño muestral.
    • Mantiene registro de recetas y pasos aplicados.
  2. Clase Step
    • Define transformaciones individuales.
    • Gestiona dependencias y evaluación perezosa.
  3. Clase Recipe
    • Agrupa steps y metadatos del proceso.
    • Facilita compartir flujos de trabajo.
    • Incluye DOI para citación académica.
  4. Clase RotativePanelSurvey y PoolSurvey
    • Extensiones para casos específicos (paneles rotativos y combinación de encuestas)
    • Implementan estimadores específicos para estos casos y permiten calcular medias moviles.

La arquitectura modular facilita la extensión del paquete y protege los objetos mediante encapsulamiento.

4.1.3 Implementación de Meta-programación

La meta-programación en metasurvey cumple tres objetivos principales:

  1. Registro Automático de Transformaciones
    • Cada operación realizada en una encuesta se registra automáticamente
    • Facilita la replicabilidad y transparencia de los análisis
  2. Evaluación Perezosa
    • Las transformaciones se aplican solo cuando es necesario
    • Optimiza el rendimiento y uso de memoria
  3. Gestión de Dependencias
    • Identificación automática de variables dependientes
    • Asegura la correcta aplicación de transformaciones en el orden adecuado

Implementar la evaluación perezosa y dependencias resultó un gran desafío, ya que requirió un diseño cuidadoso de los métodos para poder trabajar con las expresiones de R y extraer información de las mismas. La meta-programación se encuentra en casi toda la implementación de los Step y de las funciones auxiliares que permiten la creación y aplicación de recetas y pasos. Dentro de esta misma sintaxis se permite extraer las expresiones para luego poder compartir las recetas o poder decidir en que momento se aplican los pasos y recetas a la encuesta.

4.1.4 Ejemplos de la implementación

Carga de una encuesta

El paquete puede dividirse en dos partes principales: la carga y procesamiento de encuestas, y la estimación de los errores estándar. Dentro de lo que es la carga y procesamiento de las encuestas, se incluyen funciones para cargar las encuestas en diferentes formatos, como son SPSS, STATA, CSV, y RDS, y para realizar operaciones básicas como la selección de variables, la recodificación de categorías, y la creación de indicadores.

Esta implementación puede verse en load_survey.R donde aquí se define la función principal load_survey esta misma carga la encuesta y realiza las operaciones básicas mencionadas anteriormente. Dentro de ella se puede ver que es simplemente un wrapper de diferentes paquetes para cargar la encuesta ya sea read.spss del paquete foregin (R Core Team, 2023) para cargar encuestas provenientes en formato SAV o DTA, fread de data.table (Barrett et al., 2024) para archivos CSV y por último loadWorkbook del paquete openxlsx (Schauberger y Walker 2024), todas estas funciones se encargan de cargar la encuesta en base a la extensión del archivo, el usuario puede modificar cambiando el engine como por ejemplo a tidyverse donde la lectura CSV se realiza con read_csv del paquete readr (Wickham, 2023), o haven (Wickham, Miller, y Smith, 2023) para cargar encuestas en formato SPSS o STATA.

Al cargar la encuesta el usuario debe de especificar el tipo de encuesta que está cargando y la edición de la misma como el tipo de encuesta y la edición de la misma como se puede ver en Código 4.1, estos metadatos serán cruciales para poder obtener recetas y pasos de la API de metasurvey. Además, se puede especificar el tipo de réplica que se desea utilizar, por defecto se utiliza el método de BRR, pero el usuario puede especificar el método de réplica que desee, ya sea Jackknife o Bootstrap, en el Capítulo 5 se especifica como utilizar replicas brindadas por la institución que publica los microdatos y estimadores de medias móviles.

Una vez definida la carga de datos, dentro de la misma implementación se crea un objeto de la clase Survey, la cual, se encuentra definida en survey.R. Esta clase es realizada con el paquete R6 (Chang, 2022) y se encarga de almacenar los microdatos de la encuesta, los metadatos, las recetas y los pasos junto al diseño muestral, el usuario puede obtener información con wrappers de cada método para que sea más sencillo de utilizar, como por ejemplo cat_steps donde se obtiene todos los pasos que fueron aplicados a la encuesta, cat_recipes donde se obtienen todas las recetas que fueron aplicadas a la encuesta, cat_design donde se obtiene el diseño muestral, entre otros.

En el código 4.1 se muestra un ejemplo de cómo se carga una encuesta y se obtiene la información de la misma.

Código 4.1: Lectura de la encuesta ECH 2022, fijación del ponderador y obtención de recetas.
Código
library(metasurvey)

# Cargar encuesta

## Encuesta ECH 2022
## Se fija el ponderador de la encuesta
## Se obtienen las recetas de la encuesta

ech_2022 <- load_survey(
    metasurvey::load_survey_example(
        "ech",
        "ech_2022"
    ),
    svy_edition = "2022",
    svy_type = "ech",
    svy_weight = add_weight(annual = "w_ano"),
    recipes = get_recipe(
        "ech",
        "2022"
    )
)

Dentro de este mismo ejemplo se puede ver que se fija el ponderador de la encuesta, en este caso se fija el ponderador w_ano que es el ponderador anual de la encuesta ECH 2022, este ponderador es crucial para la estimación de errores estándar y para la obtención de recetas y pasos de la encuesta.

Clase Step

La clase Step es una clase que se encarga de almacenar los pasos que se aplican a la encuesta, esta clase se encuentra definida en step.R y se encarga de almacenar los pasos que se aplican a la encuesta, los pasos se aplican a través de recetas que se obtienen de la API de metasurvey, los pasos pueden ser de diferentes tipos, como por ejemplo step_compute que se encarga de calcular una variable, step_recode que se encarga de recodificar una variable, entre otros.

En el Código 4.2 se muestra un ejemplo de cómo se crea un objeto de la clase Step con una clase de R6 (Chang, 2022) paquete que permite la programación orientada a objetos en R donde tiene aquí se encuentran los atributos de la clase Step como name, edition, survey_type, type, new_var, exprs, call, svy_before, default_engine, depends_on, comments, bake en conjunto con el método initialize que se encarga de inicializar la clase Step con los atributos mencionados anteriormente. Los objetos Survey, Recipe, PanelRotativeSurvey y PoolSurvey son clases que se encuentran definidas en el paquete metasurvey donde modelar en una clase los diferentes objetos que se utilizan en el paquete permite una mejor organización y estructura del código y facilita la implementación de la meta-programación.

Es importante mencionar que la clase Step es una clase que se utiliza internamente en el paquete y no es necesario que el usuario la utilice directamente, sin embargo, es importante mencionarla ya que es una parte esencial del paquete y es utilizada en la implementación de las recetas y pasos de la encuesta, además de que es un ejemplo claro de cómo se puede utilizar la programación orientada a objetos en R para modelar diferentes objetos y clases.

Código 4.2: Definición de la clase Step con sus atributos y método initialize para inicializar la clase. Las clases de R6 son encapsuladas y permiten que los métodos y atributos sean privados o públicos.
Código
step <- R6Class(
    "Step",
    public = list(
        name = NULL,
        edition = NULL,
        survey_type = NULL,
        type = NULL,
        new_var = NULL,
        exprs = NULL,
        call = NULL,
        svy_before = NULL,
        default_engine = NULL,
        depends_on = list(),
        comments = NULL,
        bake = NULL,
        initialize = function(...args) {
            self$name <- name
            # Inicialización de los atributos de la clase
            # Se omiten por la extensión del código
            # Definir un constructor permite que siempre
            # se inicialicen los atributos de la clase
            # de forma correcta
        },
        method1 = function(...) {
            # Método 1 (Método generico no se muestra por extensión)
        },
        method2 = function(...) {
            # Método 2 (Método generico no se muestra por extensión)
        }
    )
)

El principal uso de R6 y no de S3 o S4 es que R6 permite la creación de objetos con estado en conjunto con su propiedad de encapsulamiento, lo cual es esencial para la implementación de la meta-programación, ya que permite almacenar el estado de los objetos y modificarlos a través de métodos, lo cual es esencial para la implementación de las recetas y pasos de la encuesta. Además se puede manejar las copias de los objetos de forma más sencilla siendo algo que mejora el rendimiento y la eficiencia del paquete.

Lazy evaluation

La evaluación perezosa es una técnica de programación que consiste en retrasar la evaluación de una expresión hasta que sea necesaria. En el contexto de metasurvey, la evaluación perezosa se utiliza para retrasar la aplicación de recetas y pasos a la encuesta hasta que sea necesario, lo cual permite optimizar el rendimiento y la eficiencia del paquete. Esto hace que los Steps se ejecuten con una validación mínima en base a las dependencias de las variables, y se ejecuten solo cuando se necesiten o al cocinar la receta.

El paquete tiene por defecto la evaluación perezosa de los pasos y recetas, lo cual hace que sea más eficiente y rápido el procesamiento de las encuestas aunque puede llevar a confusiones al usuario cuando revisa los datos de forma manual ya que si bien se aplican los Step los mismos no tienen efecto hasta que se cocine la receta, el usuario puede desactivar (código 4.3) la evaluación perezosa de los pasos y recetas si lo desea. La evaluación perezosa se implementa a través de la clase Step y de la función bake que se encarga de aplicar los pasos y recetas a la encuesta.

Código 4.3: Forma de desactivar la evaluación perezosa de los pasos y recetas. Esto hace que los pasos y recetas se apliquen de forma inmediata.
Código
metasurvey::set_lazy_processing(FALSE)

Uso de copias y referencias

El paquete data.table (Barrett et al., 2024) logra una eficiencia en la manipulación de datos al utilizar referencias en lugar de copias. Dentro de metasurvey al utilizar como motor data.table permite que sea eficiente y rápido aunque puede llevar a confusiones al usuario donde se modifican las referencias de los objetos algo que no es común en R, sin embargo, se puede utilizar la función copy para realizar copias de los objetos y no modificar las referencias de los mismos código 4.4.

Código 4.4: Desactivar el uso de referencias y utilizar copias de los objetos.
Código
metasurvey::set_use_copy(TRUE)

4.1.5 Meta-programación

La meta-programación fue un aspecto clave en el desarrollo de metasurvey, ya que permitió que al realizar una operación en una encuesta, se generara un registro de los pasos y recetas aplicados, lo cual es esencial para la replicabilidad y la transparencia de los análisis. La meta-programación se implementó a través de la clase Survey y de las funciones auxiliares que permiten la creación y aplicación de recetas y pasos.

Código 4.5: Ejemplo de función para encontrar dependencias de variables en una expresión de un step. Puede encontrar más ejemplos en el código fuente en la implementación de los Steps.
Código
find_dependencies <- function(call_expr, survey) {
    dependencies <- character()

    if (is.call(call_expr)) {
        for (i in seq_along(call_expr)) {
            result <- find_dependencies(call_expr[[i]], survey)
            if (!is.null(result)) {
                dependencies <- unique(c(dependencies, result))
            }
        }
    } else if (
        is.name(call_expr) && as.character(call_expr) %in% names(survey)
    ) {
        dependencies <- unique(c(dependencies, as.character(call_expr)))
    }

    return(unique(dependencies))
}

En el código 4.5 se muestra una función auxiliar que permite encontrar las dependencias de variables en una expresión de un Step. Esta función se utiliza para identificar las variables que se utilizan en un paso y que deben ser incluidas en el registro de recetas. La función find_dependencies recibe una expresión de un paso y un objeto de la clase Survey, y devuelve un vector con las variables que se utilizan en el paso. Esta función se utiliza de forma interna en las implementaciones de step_compute y step_recode para registrar las dependencias esto es un ejemplo claro de como con código se puede extraer información del mismo y utilizarla para otros fines.

La meta-programación también fue utilizada para que el usuario utilice la misma sintaxis del paquete survey para definir los parámetros o indicadores a estimar y no deba de incluir el diseño el cual ya se encuentra dentro del objeto Survey, donde aquí también se encuentran diferentes diseños en base a la periodicidad de la encuesta, algo que es útil cuando se trabaja con encuestas de panel rotativos como la ECH luego de cambio de metodología en 2021, en el Capítulo 5 se menciona como se puede utilizar diferentes diseños en base a la periodicidad de los microdatos o parámetros a estimar y un ejemplo con la encuesta ECH.

Ejemplos Avanzados de Meta-programación

La meta-programación avanzada en R permite manipular ambientes y expresiones de forma dinámica, lo cual es esencial para la implementación de recetas y pasos en metasurvey. A continuación, se presentan casos típicos de meta-programación, la manipulación de ambientes y expresiones, y el uso de substitute y bquote para evaluar expresiones de forma parcial.

Ambientes y Evaluación
Código 4.6: En este ejemplo se crea un nuevo ambiente env y se asignan valores a las variables x
Código
# Crear un nuevo ambiente
env <- new.env()

# Asignar valores en el nuevo ambiente
assign("x", 10, envir = env)
assign("y", 20, envir = env)

# Evaluar una expresión en el nuevo ambiente
eval(quote(x + y), envir = env)
Manipulación de Expresiones
Código 4.7: Evaluar una expresión en un ambiente y modificar la expresión para evaluarla de forma distinta.
Código
# Crear una expresión
expr <- quote(x + y)

# Modificar la expresión
expr[[1]] <- quote(`*`)
expr[[2]] <- quote(x)
expr[[3]] <- quote(y)

# Evaluar la nueva expresión
eval(expr, envir = env)
Uso de substitute y bquote
Código 4.8: En este ejemplo se muestra cómo se pueden reemplazar variables en una expresión utilizando substitute y cómo se puede evaluar parcialmente una expresión utilizando bquote.
Código
# Usar substitute para reemplazar variables en una expresión
expr <- quote(a + b)
substitute(expr, list(a = 1, b = 2))

# Usar bquote para evaluar parcialmente una expresión
bquote(a + .(b))

Estos ejemplos muestran cómo se pueden manipular ambientes y expresiones en R para realizar meta-programación avanzada. La capacidad de modificar y evaluar expresiones dinámicamente es una herramienta poderosa que se utiliza en metasurvey para registrar y aplicar transformaciones y brindar la flexibilidad necesaria para adaptarse a diferentes tipos de encuestas y diseños muestrales.

4.1.6 Sistema de Comunicación y Optimización

El paquete implementa una API REST desarrollada en Node.js que permite compartir y gestionar recetas entre usuarios. La API proporciona endpoints para obtener, crear y actualizar recetas, almacenadas en MongoDB. El sistema incluye autenticación mediante tokens JWT, con planes futuros para implementar un portal web de registro automático.

MongoDB se eligió por su flexibilidad y escalabilidad, permitiendo almacenar recetas de forma estructurada y eficiente. Es un sistema de base de datos NoSQL (Not Only SQL) enfocada en documentos, en lugar de tablas, se agrupan en colecciones y se almacenan en formato JSON. Esto permite almacenar recetas de forma flexible y escalable, sin necesidad de definir un esquema fijo.

Si bien dentro de la configuración de la API se define un esquema semi-estructurado para las recetas, se permite la flexibilidad de agregar nuevos campos y estructuras de datos pero se mantiene una estructura mínima para mantener la consistencia de los datos. La API se comunica con el paquete metasurvey a través de solicitudes HTTP el usuario no necesita interactuar directamente con la API ya que el paquete se encarga de la comunicación con la misma. API de metasurvey con MongoDB. La API permite compartir y gestionar recetas entre usuarios, almacenadas en MongoDB.

Para optimizar el rendimiento, se implementó un sistema de cache que gestiona proactivamente la memoria mediante liberación de recursos y reutilización de cálculos intermedios. El sistema aprovecha la paralelización automática y el procesamiento por lotes cuando es posible.

La arquitectura modular del sistema facilita la incorporación de nuevos tipos de encuestas y diseños muestrales, permitiendo adaptarse a diferentes necesidades sin modificar el núcleo del paquete.

4.2 Síntesis del capítulo

En este capítulo se ha presentado los diferentes objetos dentro del paquete, así como su implementación en el paquete metasurvey. Además, se ha mostrado cómo metasurvey facilita la creación y el manejo de encuestas, permitiendo a los usuarios obtener transformaciones transparentes y reproducibles.