Consumo de Datos vía APIs con `httr2`

Construyendo un dashboard de monitoreo y análisis con datos en tiempo real.

El Siguiente Nivel: Datos Vivos

Ya hemos demostrado que una base de datos local supera a un archivo plano. Pero, ¿qué pasa si los datos se actualizan constantemente en una fuente externa? Aquí es donde las APIs brillan. Una API nos permite consultar datos "vivos" directamente desde su origen.

En esta lección, diseñaremos una aplicación `shinydashboard` que no solo consume datos de la API de Datos Abiertos de Colombia, sino que también compara su rendimiento con nuestros métodos locales, dándonos una visión completa de las estrategias de acceso a datos.

El Poder de SoQL: SQL en la URL

El portal de Datos Abiertos de Colombia está construido sobre Socrata, una plataforma que ofrece un potente lenguaje de consulta llamado SoQL (Socrata Open Data API Query Language). SoQL nos permite escribir cláusulas similares a SQL directamente en los parámetros de la URL.

Esto es revolucionario porque significa que podemos delegar el trabajo pesado (filtrar, ordenar, agregar) al servidor de la API, y recibir solo los datos precisos que necesitamos. Es el equivalente a que el mesero no solo te traiga el plato, sino que le pida al chef que lo prepare exactamente como lo quieres.

El Dataset: Usaremos el conjunto de datos unificado "Resultados únicos Saber 11".

Blueprint del Dashboard Avanzado

Nuestra aplicación tendrá dos pestañas:

Pestaña 1: Monitoreo de Rendimiento (3 Vías)

Esta pestaña ejecutará la misma consulta lógica a través de tres métodos y medirá el tiempo de cada uno:

  1. Archivo Plano: Carga el `.txt` completo en memoria y filtra con `dplyr`.
  2. Base de Datos SQLite: Envía una consulta SQL a nuestra base de datos local.
  3. API de Datos Abiertos: Envía una consulta SoQL al servidor de Socrata.

El código en el servidor para el nuevo método de API se vería así:


# Dentro del observeEvent(input$run_benchmark, { ... })

# --- Método 3: API de Datos Abiertos (SoQL) ---
start_time_api <- Sys.time()

base_url <- "https://www.datos.gov.co/resource/kgxf-xxbe.json"
query_soql <- "
    SELECT avg(puntaje_global)
    WHERE naturaleza_colegio = 'OFICIAL' AND municipio_ubicacion = 'BOGOTA D.C.' AND periodo = '20234'
"
req_api <- request(base_url) %>%
    req_url_query(`$query` = query_soql)

resp_api <- req_perform(req_api)
resultado_api <- resp_body_json(resp_api, simplifyVector = TRUE)

end_time_api <- Sys.time()
benchmark_results$time_api <- as.numeric(difftime(end_time_api, start_time_api, units = "secs"))

Pestaña 2: Dashboard de Análisis con Datos en Vivo

Esta pestaña será un explorador de datos completamente funcional que obtiene su información directamente de la API. Los `selectInput` del usuario (para periodo y departamento) construirán dinámicamente una consulta SoQL.

Construcción Dinámica de la Consulta

El núcleo de esta pestaña es un conductor reactivo que crea la consulta SoQL basándose en los inputs del usuario.


# En el server de la app

datos_api_reactivos <- reactive({
    req(input$periodo_select, input$depto_select) # Asegura que los inputs no estén vacíos

    # Construye la cláusula WHERE dinámicamente
    where_clause <- sprintf(
        "departamento_ubicacion = '%s' AND periodo = '%s'",
        toupper(input$depto_select),
        input$periodo_select
    )

    # Construye la consulta SoQL completa
    query_soql <- sprintf(
        "SELECT puntaje_global, puntaje_matematicas, naturaleza_colegio, nombre_colegio
         WHERE %s
         ORDER BY puntaje_global DESC
         LIMIT 100",
        where_clause
    )

    # Realiza la llamada a la API con esta consulta
    base_url <- "https://www.datos.gov.co/resource/kgxf-xxbe.json"
    req <- request(base_url) %>% req_url_query(`$query` = query_soql)
    resp <- req_perform(req)
    
    # Procesa y devuelve los datos como un tibble limpio
    resultados <- as_tibble(resp_body_json(resp, simplifyVector = TRUE)) %>%
        mutate(across(starts_with("puntaje"), as.numeric))
    
    return(resultados)
})

# Ahora, los outputs (gráficos, tablas) simplemente leen de `datos_api_reactivos()`
output$grafico_api <- renderPlotly({
    plot_ly(datos_api_reactivos(), x = ~puntaje_matematicas, y = ~puntaje_global, ...)
})

La Verdadera Ventaja

Con este diseño, si el ICFES publica los datos de un nuevo periodo en el portal, nuestro dashboard lo reflejará automáticamente (una vez que se añada el nuevo periodo a las opciones del `selectInput`). No necesitamos ejecutar pipelines ETL ni gestionar archivos locales. La aplicación está siempre sincronizada con la fuente de verdad oficial.