Creando Artefactos de Procesamiento de Datos

El pilar de MLOps para desacoplar, versionar y reutilizar la lógica de datos.

El Principio MLOps: Desacoplar Lógica

En el desarrollo de software y MLOps, un principio fundamental es la **separación de responsabilidades**. Esto significa que cada pieza de nuestro sistema debe hacer una sola cosa y hacerla bien. Mezclar la lógica de preparación de datos con la lógica de la interfaz de usuario (la app Shiny) es una receta para el "spaghetti code": un sistema frágil, difícil de depurar y imposible de escalar.

Por eso, nuestro objetivo en esta lección no es solo aprender a usar `dplyr`. Es aprender a encapsular nuestras transformaciones de datos en un **artefacto**: un script de R (`.R`) autocontenido, versionable y reutilizable. Este script se convierte en un componente fundamental de nuestro pipeline de MLOps, que podremos probar de forma aislada y consumir desde nuestra aplicación Shiny o cualquier otro proceso.

La Herramienta: Verbos Esenciales de `dplyr`

Para construir nuestro artefacto de procesamiento, usaremos `dplyr`. Sus "verbos" nos permiten escribir pasos de transformación de datos que son tan legibles como una receta de cocina.

select() y filter()

`select()` elige columnas por su nombre. `filter()` elige filas basadas en una condición lógica.

# Selecciona solo las columnas de puntaje y filtra por colegios oficiales
datos_limpios <- datos_saber %>%
  select(starts_with("punt_"), cole_naturaleza) %>%
  filter(cole_naturaleza == "OFICIAL")

mutate()

Crea nuevas columnas o modifica existentes. Es el corazón de la ingeniería de características (feature engineering).

# Crea una nueva columna que promedia los puntajes de ciencias y matemáticas
datos_enriquecidos <- datos_saber %>%
  mutate(promedio_ciencias_mat = (punt_ciencias_naturales + punt_matematicas) / 2)

group_by() y summarise()

Trabajan juntos para realizar resúmenes agregados. `group_by()` define los grupos y `summarise()` calcula métricas para cada uno.

# Calcula el puntaje global promedio para cada tipo de colegio
resumen_por_naturaleza <- datos_saber %>%
  group_by(cole_naturaleza) %>%
  summarise(
    puntaje_promedio = mean(punt_global, na.rm = TRUE),
    total_estudiantes = n()
  )

Guía Práctica: Construcción e Integración del Artefacto

Ahora que conocemos las herramientas, vamos a aplicar estos principios para crear nuestro primer artefacto de procesamiento y conectarlo a la aplicación, siguiendo la estructura de proyecto definida en el Módulo 1.

Paso 1: Ubicar el Artefacto en la Estructura del Proyecto

El primer paso es saber dónde vivirá nuestro nuevo componente. Según la arquitectura MLOps que establecimos, toda la lógica de R reutilizable (funciones de procesamiento, modelado, etc.) debe residir en la carpeta `/R`.

  • mi-proyecto/
    • data/
    • R/
      • data_processing.R    <-- NUESTRO ARTEFACTO
    • global.R
    • server.R
    • ui.R

Acción: En tu proyecto, dentro de la carpeta `/R`, crea un nuevo archivo llamado `data_processing.R`.

Paso 2: Desarrollar el Pipeline dentro de una Función

Ahora, escribimos el pipeline de `dplyr`. Es una práctica recomendada envolverlo en una función. Esto lo hace reutilizable y fácil de probar de forma independiente.

Acción: Abre `R/data_processing.R` y añade el siguiente código.

# Contenido del artefacto: R/data_processing.R

prepare_saber_data <- function(raw_data) {
  
  message("Ejecutando pipeline de preparación de datos...")
  
  processed_data <- raw_data %>%
    na.omit() %>%
    mutate(
      rendimiento_global = case_when(
        punt_global >= 350 ~ "Alto",
        punt_global >= 250 ~ "Medio",
        TRUE ~ "Bajo"
      )
    ) %>%
    select(
      starts_with("punt_"),
      cole_naturaleza,
      rendimiento_global
    )
    
  return(processed_data)
}

Paso 3: Integrar el Artefacto en la Aplicación

Nuestra aplicación Shiny ahora no procesará los datos directamente. En su lugar, actuará como un **consumidor** de nuestro artefacto. El punto de integración es el archivo `global.R`, que se ejecuta una sola vez al inicio de la aplicación y actúa como nuestro orquestador principal.

Acción: Modifica tu archivo `global.R` para que cargue el script del artefacto y lo utilice.

# En global.R

# ... (tus librerías: library(shiny), library(dplyr), etc.) ...

# 1. Cargar el artefacto de procesamiento de datos
source("R/data_processing.R")

# 2. Cargar los datos crudos
datos_crudos <- read_delim("data/raw/Examen_Saber_11_20242.txt", delim = ";", show_col_types = FALSE)

# 3. Ejecutar el pipeline para crear el dataframe limpio que usará la app
datos_saber <- prepare_saber_data(datos_crudos)

# ... (el resto de tu código de global.R) ...

El Nuevo Flujo de Datos MLOps

Con este cambio, hemos establecido un flujo claro y desacoplado:

  1. `global.R` actúa como orquestador: carga los datos crudos.
  2. Llama a la función desde nuestro artefacto (`R/data_processing.R`) para procesarlos.
  3. El resultado (datos_saber) es un dataframe limpio y listo para ser usado por la lógica reactiva en `server.R`.

Paso 4: Versionar el Nuevo Artefacto

Has creado un componente de software modular. Este es un hito importante en el ciclo de vida del proyecto y debe ser registrado en Git con un mensaje que refleje su importancia.

# Añade el nuevo artefacto y los cambios en el orquestador
git add R/data_processing.R global.R

# Un commit que describe la creación de un componente MLOps
git commit -m "feat(data): Crea artefacto de procesamiento de datos y lo integra en la app"

git push