Datos abiertos

datos abiertos
scraping
Autor/a

Miguel Equihua

Fecha de publicación

Xalapa, Ver., 10 de abril, 2025

La preparación, oferta y mantenimiento de datos abiertos es parte de los intereses en búsqueda de una ciencia abierta. En este sentido conviene considerar los principios de la iniciativa de Budapest, Hungría en torno a publicación abierta. Esta iniciativa fue publicada el 14 de febrero 2002. Especialmente importante resulta la recomendación de desarrollar capacidades de “self-archiving” siguiendo estándares de la iniciativa de repositorios abiertos. Aunque esta última propuesta ya nos está en desarrollo activo, fue el antecedente que dio origen al estándar ANSI/NISO Z39.99-2017 para el acceso bibliográfico. De aquí emerge tamién el protocolo de cosecha de metadatos OAI-PMH, cuyas especificaciones continúan vigentes, y tiene nuevos desarrollos o actualizaciones como el ANSI/NISO 2017 aunque no se trata necesariamente de un reemplazo. De la iniciativa de Budapest emerge una guía interesante en torno al establecimiento de repositorios institucionales (de publicaciones). En su propio manifiesto del 2023, REDALYC refrenda los valores enunciados en la iniciativa de Budapest.

En México se han tenido expresiones positivas en torno a esta iniciativa desde su aparición en 2002. Por ejemplo, del Senado de la República, la UNAM, UAEM, CONACYT y la UAM, entre otras. Si bien la iniciativa de Budapest se enfoca en la publicación abierta, resulta claro que no basta con tener acceso a la publicación como producto final de las investigaciones, se requiere compartir también los datos base de los estudios, como se explica en esta nota de Verhulst, Zahuranec & Young (2021), que retoma parte de la serie “Great Stories of Open Science” que se publica con el apoyo del Ministerio Francés de Educación Superior, Investigación e Innovación

 

Actualmente, la opción vigente para datos abiertos nos conduce a los principios FAIR, que son un conjunto de recomendaciones para la gestión y cuidado de los datos científicos . La sigla FAIR se propone como adjetivo para calificar a los datos científicos como contenido digital, en virtud de su Findability, Accessibility, Interoperability, and Reuse. Existe el sitio goFAIR que promueve la adopción de estos principios (Giadrossich et al., 2025) .

Un ejemplo del proceso de adopción de los principios FAIR se presenta en el reporte aparecido en 2018 de la experiencia europea: Turning FAIR into reality: final report and action plan from the European Commission expert group on FAIR data, Publications Office. En este mismo sentido y en la confluencia de esfuerzos que impulsan los valores de la ciencia abierta esta también SPARC, que es una organización Norteamericana con filiales en Europa, África y Japón, sin fines de lucro. Promueve el desarrollo de sistemas para la investigación y la educación que sean abiertos en forma predeterminada y equitativos por diseño. La experiencia europea de SPARC ha producido documentos útiles como referencia y fuente de inspiración:


A la par de los atributos que definen la calidad y apertura práctica de los datos, hay que considerar la necesidad de mantenerlos en las mejores condiciones posibles, es decir curarlos. Al respecto, son importantes las recomendaciones que ofrece el Digital Curation Center. El lema que anima a esta organización es suficientemente elocuente: ¡Porque la buena investigación necesita buenos datos!.

Esta misma organización ofrece orientación para la definición de metadatos por áreas del conocimiento, lo que resulta muy útil. La página ofrece colecciones de estándares existentes y ayudan así al interesado a conocer las diversas aproximaciones que se han ensayado.

De acuerdo con los criterios que emanan de los principio FAIR, los datos pueden estar en distintos niveles de acceso abierto. Así, se puede definir la escalera de estructuración y acceso. En el nivel más simple encontramos datos contenidos en documentos de texto, por ejemplo PDF. En el otro extremo, con plena accesibilidad digital, están los verdaderos datos abiertos que cumplen a plenitud con los criterio FAIR.



Ejemplos de soluciones de datos abiertos

Uniatmos

Es la Unidad de Informática para las Ciencias Atmosféricas y Ambientales gestionada por el Instituto de de la Atmósfera y Cambio Climático de la UNAM.

Zenodo

Se trata de un espacio construido y desarrollado por investigadores, para garantizar que todo el mundo pueda participar en la Ciencia Abierta. El proyecto OpenAIRE fue desarrollado por indicaciones la Comunidad Europea para apoyar su incipiente política de Datos Abiertos. Con esta plataforma se ofrece un repositorio general para la investigación financiada por la Comnidad Europea. El CERN, socio de OpenAIRE y pionero en código abierto, acceso abierto y datos abiertos, proporcionó esta capacidad para lograr que Zenodo estuviera en operación a partir de mayo de 2013. En apoyo de su programa de investigación, el CERN ha desarrollado herramientas para la gestión de Big Data y ha ampliado las capacidades de la biblioteca digital para Open Data. A través de Zenodo, estas herramientas de Big Science pueden así compartirse eficazmente.

Datadryad

Es una plataforma de publicación de datos abiertos y una comunidad comprometida con la disponibilidad abierta y la reutilización rutinaria de todos los datos de investigación.

Figshare

Es un repositorio en el que los usuarios pueden poner a disposición todos los resultados de sus investigaciones de forma que se puedan citar, compartir y descubrir.

Metadatos y ejemplos de datos abiertos

Unión Europea: datos abiertos

Metadatos ámbito biológico: Darwin Core

Metadatos ámbito ciencias de la Tierra ISO-19115

La documentación de los metadatos cartográficos que utiliza Conabio sigue los estándares definidos en FGDC (1998) y FGDC (1999). De acuerdo con lo qe nos explicó el Ing. Fernández, el estándar de metadatos FGDC ha sido remplazado actualmente por el ISO-19115.

Otros ejemplos con datos climáticos y ambientales en general

Datos abiertos para principiantes

El grupo Safe Software produjo este libro electrónico, que explica en forma sencilla asuntos importantes a tener en cuenta.

Mantenlo simple

Inicia con asuntos pequeños, simples y de solución rápida. No hay necesidad de correr a abrir todos los datos de inmediato. Hacer de acceso abierto un conjunto pequeño de datos o parte del big data es suficiente para empezar y ganar experiencia.

Involucrarse pronto y hacerlo frecuentemente

Hay que acercarse tan pronto como sea posible a los usuarios reales y potenciales. Hay que pensar en quienes podrían utilizar los datos para crear otros productos de información. Estos actores pueden ser ciudadanos, empresarios, desarrolladores o intermediarios.

Atender los miedos y malos entendidos comunes

Esto es especialmente importante si estas trabajando con o dentro de una institución grande como suelen ser las áreas gubernamentales. Cuando se trata de abrir los acervos de datos es de esperar que surjan muchas preguntas, dudas y temores. Es importante identificar los más importantes de ellos y enfrentarlos de inmediato.

Recursos para facilitar el compartir

Indautor

Puedes visitar en México el Instituto Nacional del Derecho de Autor para obtener más información.

 

¿Cómo podemos usar datos abiertos?

Ahora te propongo pasar a la práctica y explorar algunas cosas que te darán idea de como es que puedes aprovechar datos abiertos de tu interés. En el caso de México, como ya comenté, Inegi, Conabio y en general datos.gob.mx son referencias importantes de proveedores de datos de México. Te propongo ver algunos ejemplos de como puedes aprovechar estos datos. Desde luego, una forma de hacerlo es por la ruta de descargar lo que necesites y a partir de ahí hacer tu procesamiento de valor agregado para generar nuevos productos de información que se alinean con los fines de tu proyecto. Otra forma de hacerlo es recurriendo a canales de flujo de datos que muchas veces se pueden aprovechar mediante el uso de API (Interfaz de Programación de Aplicaciones). Las API son creadas, diseñadas y utilizadas para lograr una interacción ordenada y coherente entre aplicaciones, sin necesidad de saber más que las especificaciones que definen a la API y nada de la estructura interna del servicio que deseamos utilizar. Naturalmente Esto simplifica el desarrollo de nuevas aplicaciones. No es mi pretención cubrir ampliamente el tema, pero considero potencialmente interesante para ti saber algo de este tema, que te abre las puertas al acceso a muchas cosas en la World Wide Web actual. Te presentaré algunos ejemplos y espero me propongas ideas de como utilizar estas ideas en tu proyecto.

datos.gob.mx

Para empezar, debes saber que estos datos están cubiertos por la licencia libre uso MX. Esta licencia busca promover el uso, reuso y redistribución de conjuntos de datos de acuerdo con una serie de criterios que se especificán aquí y que indica, entre otras cosas que puedes:

  • Hacer y distribuir copias del conjunto de datos y su contenido;
  • Difundir y publicar el conjunto de datos y su contenido;
  • Adaptar o reordenar el conjunto de datos y su contenido;
  • Extraer total o parcialmente el contenido del conjunto de datos;
  • Explotar comercialmente el conjunto de datos y su contenido, y;
  • Crear conjuntos de datos derivados del conjunto de datos o su contenido.

Al experimentar con los ejemplos que siguen, encontré que puede ocurrir que los sitios que distribuyen los datoss no estén disponibles momentaneamente (¡a veces por varios días!). Esto puede ser frustante y complicar la operación de los escrips de cómputo, en R o en cualquier otro lenguaje. Aprovecharé esta dificultad para demostrar el uso de una función en R que te ayuda a que tus algoritmos no se interrumpan en caso de fallas como esta. Se trata de la función trycatch que observa como se ejecuta un conjunto de instrucciones y en caso de error, “atrapa” la falla y dirige el proceso a lo que hayas previsto para manejarla en la opción error. La estrucura de esto es la siguiente.

trycatch(
  { pones aquí las intrucciones que quieres vigilar}
,
 error = function(cond)
  { pones dentro de estos corchetes las instrucciones a operar en caso de error}
 )

Si todo operó con normalidad, las instrucciones en la primera parte se habrán desarrollado sin falla y entregarán los resultados que deseas. En caso de falla, quizás quieras un reporte de la falla, codificada en la variable cond y registrar algún valor para avisar en otras partes que algunos datos podrían no estar presentes.

Catálogo de datos existentes datos.gob.mx

Ahora veamos algunos ejemplos de como interactuar con esos datos mediante la API.

muestra el escript:
pacman::p_load(jsonlite, tidyverse, DT, rvest, httr2)

tryCatch(
  {
    req <- request("https://api.datos.gob.mx/v1/api-catalog?pageSize=10000")
    resp <- req_perform(req)
    
    dat_1 <- fromJSON(resp_body_string(resp))
    dat_1_df <- dat_1$results
    
    for (i in 1:length(dat_1_df$variables))
    {
      dat_1_df$variables[i] <- paste(dat_1_df$variables[[i]], collapse = ",")
    }
    
    dat_1_df$variables <- unlist(dat_1_df$variables)
    
    dat_1_df |>
      select("endpoint", "url", "variables") |> 
      datatable()
  },
    error = function(cond) {
      print("Catálogo: datos.gob.mx no está diosponible por el momento.")
})
[1] "Catálogo: datos.gob.mx no está diosponible por el momento."

Datos de Ozono como contaminante atmosférico en ciudades de México

Del catálogo mostrado arriba, obtengo la referencia de la API al conjunto de datos que me interesa, se refiere al endpoint. En este caso se trata del sinaica, la ruta de acceso que me interesa es la URL respectiva. Lo que sigue es agregar los datos específicos que me interesan, que agregaré a la misma URL después de un signo de interrogación.

Los datos de las estaciones existentes los puedes consultar con la misma API o en la página del Sinaica, Hay un enlace a Infraestructura de los SMCA, que contiene los descriptores de cada una de las estaciones existentes en el país. Para hacerlo con la API buscamos en la tabla anterior sinaica-estaciones. Hacemos la petición así:

muestra el escript:
URL_estaciones <- "https://api.datos.gob.mx/v2/sinaica-estaciones?pageSize=1000"

tryCatch(
  {
    req_est <- request(URL_estaciones)
    resp_est <- req_perform(req_est)
    
    dat_est <- fromJSON(resp_body_string(resp_est))
    dat_est_df <- dat_est$results
    
    dat_est_df |>
      select("id", "nombre", "long", "lat") |> 
      datatable(colnames = c("idEstación", "nombre", "long", "lat       "))
},
    error = function(cond) {
      print("Ozono: datos.gob.mx no está diosponible por el momento.")
})
[1] "Ozono: datos.gob.mx no está diosponible por el momento."

Las variables que puedo usar para construir esta consulta las encuentro precisamente en la columna variables del catálogo. Para el caso de Sinaica esta columna reporta las siguientes variables disponibles.

muestra el escript:
if (exists("dat_1_df"))
  {
    dat_1_df |> 
      filter(endpoint == "sinaica") |> 
      select(variables) |>  
      separate_longer_delim(variables,  ",") |> 
      flextable::flextable() |> 
      flextable::color(i = 7:8 , color = "blue ")

} else print("Sinaica: Datos no disponibles")
[1] "Sinaica: Datos no disponibles"

Los datos que quiero para este ejercicio son el idEstación, y el nombre del parámetro, en este caso O3. Hay un dato pageSize, que se refiere al máximo de registros que esperamos recibir por página. Con estos datos construimos la URL necesaria.

URL: https://api.datos.gob.mx/v2/sinaica
pagesize: 8000
parametro: O3
estacionesid: 259  # es la del Pedregal de San ángel, Álvaro Obregón, CdMx
page: 1

Combino todos estos parámetros con el caracter & como separador de items y lo agrego todo al final de la URL.El resultado debe verse así.

https://api.datos.gob.mx/v2/sinaica?pageSize=8000&parametro=O3&estacionesid=259&page=1

 

Ahora, estamos listos para hacer la consulta con el escript de abajo.

 

muestra el escript:
url_O3 <- "https://api.datos.gob.mx/v2/sinaica?pageSize=8000&parametro=O3&estacionesid=259&page=1"

tryCatch(
  {
    req_O3 <- request(url_O3)
    resp_O3 <- req_perform(req_O3)
    
    dat_O3 <- fromJSON(resp_body_string(resp_O3))
    dat_O3_df <- dat_O3$results
  },
    error = function(cond){
      print("Ozono-CdMx: datos.gob.mx no está diosponible por el momento.")
    })
[1] "Ozono-CdMx: datos.gob.mx no está diosponible por el momento."

 

Estos son los datos de ozono en la atmósfera medidos en la estación no los datos soliciados, de la Ciudad de México (Tabla 1).

 

muestra el escript:
if(exists("dat_O3_df"))
{
  dat_O3_df |>
    select("fecha", "hora", "valororig") |> 
    datatable(colnames = c("Fecha", "Hora", "Valor"))

} else print("Ozono: Datos no disponibles")
Tabla 1: Ozono atmosférico
[1] "Ozono: Datos no disponibles"

Datos de estaciones meteorológicas Conagua

Los datos generales de todas las estaciones climatológicas de México están publicadas como datos de acceso abierto, pero no están en forrma de tabla sino en forma de datos geográficos asociados a marcadores de puntos que se despliegan en un mapa. Se comprende que es una entrega de datos pensada para que un usuario acceda a la información en forma interactiva. Pienso que para muchos otros fines de reuso de esos datos conviene tenerlos en formato tabular. El documento geográfico está disponible en formato kmz. Este archivo es el tipo que usa Google Earth. Es una versión comprimida como un “zip”, de otro tipo de archivo que es el kml, también desarrollado y usado en Google Earth. Lo que podemos hacer es descomprimir el archivo kmz, y procesar el archivo descomprimido resultante. En R existe la función unzip. Es la que usaremos enseguida.

muestra el escript:
# descarga el archivo "kmz" de interés
url_agua <- "http://smn.conagua.gob.mx/"
url_kmz <- "tools/RESOURCES/Normales_Climatologicas/EstacionesClimatologicas.kmz"   
archivo_kmz <- "./estaciones.kmz"



err <- tryCatch({
  request(paste0(url_agua, url_kmz)) |> 
    req_perform() |> 
    resp_body_raw()|> 
    writeBin(archivo_kmz)},
  error = function(e) return(e)
)

if (!str_detect(err$message, "Failed"))
  # desempaca el "kmz" y guarda el resultado en "temp-kmz"
  unzip(zipfile = archivo_kmz, exdir = "temp-kmz")

La estrategia de procesamiento que seguiremos la orientaremos a aprovechar el hecho de que los archivos kml son ambién documentos xml, semejantes a los que se usan para producir páginas Web, para manejar este tipo de archivos existe en R la biblioteca rvest que empaca muchas heramientas interesantes para recolectar y procesar datos directamente del Internet (se le llama Web scraping a esta tarea, algo así como ¿cosechar la web?). El proceso require recorrer el documento y recolectar las piezas de información que interesan. La tarea no es sencilla, pero nos sirve de ejemplo avanzado que ilustra cosas que es posile hacer. Una vez obtenidos estos datos podría ser interesante ver formas de análisis de esttos datos generales que te imagines.

En el escript que sigue, sólo extraeremos los datos del archivo kml y los desplegaremos en forma de tabla. Los datos quedarán disponibles como una tabla tibble (la variante más moderna del data.frame original de R), que podrás usar de muchas maneras. Me gustará mucho escuchar tus ideas.

Este es el mapa a partir de los datos kmz

muestra el escript:
# carga la biblioteca para procesar el "xml"
pacman::p_load(xml2)

data <- read_html("temp-kmz//doc.kml")
xml_data <- as_list(data)

# los datoa de interés están en "folders" 
# dentro de la rama html/body/kml/document/
xml_data <- xml_data[["html"]][["body"]][["kml"]][["document"]]

# Estaciones operativas
datos_ext_opr <- xml_data[["folder"]][[3]]
                    
# Estaciones suspendidas        
datos_ext_ssp <- xml_data[["folder"]][[4]]

datos_todo <- c(datos_ext_opr, datos_ext_ssp)

for (r in datos_todo)
{
  if(!identical(r[[1]],"Estaciones operativas") &
    (!identical(r[[1]],"Estaciones suspendidas")))
  {
    e <- r$extendeddata$schemadata
    # recupera datos de la estación 
    nombres <- character(length(e)-1)
    valores <- character(length(e)-1)
    for (i in 1:(length(e)-1))
    {
        nombres[i] <- attr(e[[i]], "name")
        if (!is_empty(e[[i]])) valores[i] <- e[[i]][[1]]
    }
    
    datos_temp <- tibble(nombres, valores) %>%
      pivot_wider(names_from = nombres, values_from = valores)
    
    if (identical(r, datos_ext_opr[[2]]))
    {
      datos_est <- tibble(datos_temp)
    } else {
      datos_est <- rows_append(datos_est, datos_temp)
    }
  }
}


datos_est |> 
  select(CLAVE, ESTADO, NOMBRE, SITUACION) |> 
  datatable()
Tabla 2

Los datos de la estación de Xalapa con id: 30135, son los siguientes.

muestra el escript:
# Datos diarios Xalapa
dat_csv <- "ver/dia30135.txt"
url_meteo <- "https://smn.conagua.gob.mx/tools/RESOURCES/Normales_Climatologicas/Diarios"

url_xalapa <- paste(url_meteo, dat_csv, sep = "/")

dat_meteo_meta <- readLines(url_xalapa, n = 25)

# datos de la estación
estacion <- tibble(est = unlist(dat_meteo_meta[11:19])) |> 
  mutate(var = str_extract(est, "(.*)(?=\\s:)"),
         val = str_extract(est, "(?<=\\s:)(.*)"),
         var = str_trim(var),
         val = str_trim(val), .keep = "unused" ) |>
  pivot_wider(names_from = var, values_from = val)


# variables meteorologicas
variables <- str_split(readLines(url_xalapa, n = 24)[24], "\t")[[1]][c(1,3:6)]

# datos meteorológicos
dat_meteo <- read.csv(url_xalapa, skip = 25, sep = "\t", header = F)

names(dat_meteo) <- variables

dat_meteo |> 
  mutate(idEstacion = estacion$ESTACIÓN) |> 
  datatable()
Tabla 3: Datos meteorológios de Xalapa

Microdatos censales

Como habíamos visto en tipos de estudios Puede interesarte también ete artíulo sobre los datos abiertos que ofrece Inegi y la bilioteca para R que han desarrollado. Este otro es un ejemplo detallado de acceso y procesamiento de microdatos. Algo semejante ofrece este artículo de Castro (2021) y está también el libro completo en línea de Escoto Castillo (2021), sobre como usar microdato para analizar el mercado de tabajo. Si es de tu interés esta página de INEGI te ayudará a encontrar lo que necesitas. Por ejemplo, INEGI dispone de los microdatos del censo agropecuario 2022. Al tratar microdatos es importante que consideres las recomendaciones de seguridad de Griffiths et al. (2020).

Precios según el SNIIM

Me pareció interesante averiguar sobre mercados en el ámbito agropecuario mexicano. Encontré al SNIIM. Es el Sistema Nacional de Información e Integración de Mercados. Es un servicio que ofrece la Secretaría de Economía con el propósito de poner al alcance sel público información sobre el comportamiento de los precios al por mayor de los productos agrícolas, pecuarios y pesqueros que se comercializan en los mercados nacionales e internacionales.

Desafortunadamente, la forma como reportan los datos en la página del SNIIM es un poco complicada en términos informáticos y utiliza la tecnología de Microsoft asp.net véase este artículo sobre estas tecnologías. Lo que hacen es generar en forma dinámica una tabla con la información solicitada, pero en lugar de poner los datos en una tabla directamente, producen un iframe, es decir ofrecen sólo una especie de visor a datos que están encapsulados, aunque al desplegar el reporte producido a petición del usuario, parecería que está todo en un sólo documento que se despliega en el navegador, pero no es realmente así.

Para obtener los datos y poderlos cargar a una tabla en R, es mejor hacer una cosulta directamente a la base de datos. Para eso necesitamos algunos datos específicos que obtendremos de los siguientes catálogos que, con un poco de maña, se pueden obtener del propio sitio del SNIIM, yo ya lo hice por tí y aquí están. A continuación podrás consultar estos catálogos para que contruyas peticiones a tu gusto.

 

muestra el escript:
pacman::p_load(rvest, DT, dplyr, stringr, ggplot2, scales, htmltools)

cat_dest <- read.csv(file = "sniim-destinos.csv", quote = "'")
cat_orig <- read.csv(file = "sniim-origen.csv")
cat_frut <- read.csv(file = "sniim-frutas-hortalizas.csv")
cat_flor <- read.csv(file = "sniim-flores.csv")
cat_gran <- read.csv(file = "sniim-granos-semillas.csv")
cat_acei <- read.csv(file = "sniim-aceite.csv")
cat_insu <- read.csv(file = "sniim-insumo.csv")

cat_lugar <- cat_dest |> 
  mutate(tipo = "destino") |> 
  bind_rows(c(cat_orig, tipo = "origen"))

cat_prod <- cat_frut |> 
  mutate(tipo = "frutas y hortalizas") |> 
  bind_rows(c(cat_flor, tipo = "flores")) |> 
  bind_rows(c(cat_gran, tipo = "granos y semillas")) |> 
  bind_rows(c(cat_acei, tipo = "aceites comestibles")) |> 
  bind_rows(c(cat_insu, tipo = "insumos agrícolas"))

Lugar de Orígen y Mercado de Destino

muestra el escript:
cat_lugar |> 
  datatable() #options = list(pageLength = 1)) #, caption = tags$caption(style = "caption-side: top; text-align: center; font-weight: bold;", "Mercado de Destino"))

Productos en los Mercados Agrícolas Nacionales

muestra el escript:
cat_prod |> 
  datatable()


Hagamos un ejercicio con los precios del limón sin semilla en Xalapa, entre las fechas 01/feb/2025 y 01/may/2025. Para hacer esto necesitamos los siguientes datos.

url base: http://www.economia-sniim.gob.mx/nuevo/Consultas/MercadosNacionales/PreciosDeMercado/Agricolas/
escript de consulta:ResultadosConsultaFechaFrutasYHortalizas.aspx
generador de la tabla de datos: ResultadosConsultaFechaFrutasYHortalizas.aspx 
fechaInicio: 01/01/2025  fechaFinal: 01/05/2025  ProductoId 426  OrigenId 30  Origen Veracruz  DestinoId 301  Destino Veracruz: Central de Abasto de Jalapa  PreciosPorId 2 (este código se refiere a kg unitario)  RegistrosPorPagina 500  

Ahora, semejante a los ejemplos anteriores, tomamos la URL base y, en este caso, la juntamos con la llamada al escript que se encarga de hacer la consulta a la base de datos y le ponemos una iterrogación al final. Luego hacemos la consulta que nos interesa, agregando los datos separados por el símbolo &. Todo en una sola larga línea. Así:

http://www.economia-sniim.gob.mx/nuevo/Consultas/MercadosNacionales/PreciosDeMercado/Agricolas/ResultadosConsultaFechaFrutasYHortalizas.aspx?fechaInicio=01/02/2025&fechaFinal=01/04/2025&ProductoId=426&OrigenId=30&Origen=Veracruz&DestinoId=301&Destino=Veracruz: Central de Abasto de Jalapa&PreciosPorId= 2&RegistrosPorPagina=500

En general no conviene usar espacios entre palabras en las URL, así que se suelen substituir por el código %20. Si tu consulta llegara a fallar, esta es una cosa que podrías intentar, pero antes checa que todo se vea según tu plan. Por cierto, notarás que cada elemento de la consulta tiene un nombre de parámetro y un valor, separados por el signo “=”. Normalmente esto sugiere que el orden en el que pongas las cosas no importa, salvo la parte que está antes de la interrogación. Aquí hay algo de documentación de este servicos gubernamental.

Listo, hagamos la consulta para averiguar el patrón de precios del limón sin semilla en lo que va de 2025 en Xalapa, Ver.

 

muestra el escript:
url_limon <- "http://www.economia-sniim.gob.mx/nuevo/Consultas/MercadosNacionales/PreciosDeMercado/Agricolas/ResultadosConsultaFechaFrutasYHortalizas.aspx?fechaInicio=01/01/2025&fechaFinal=01/05/2025&ProductoId=426&OrigenId=30&Origen=Veracruz&DestinoId=301&Destino=Veracruz:%20Central%20de%20Abasto%20de%20Jalapa&PreciosPorId=2&RegistrosPorPagina=500"

page <- read_html(url_limon)

tabla_precios <- page %>% 
  html_node("table#tblResultados") %>%
  html_table(header = TRUE) %>% 
  slice(-1) %>% 
  mutate(precio_num = as.numeric(`Precio Frec`),
         feha_d = as.Date(Fecha, format = "%d/%m/%Y")) %>% 
  rename_with(., ~ str_replace_all(iconv(.x, to='latin1//TRANSLIT'), "'", ""))

# print result to console

tabla_precios |>
  select(Fecha:Obs.) |> 
  datatable()
muestra el escript:
tabla_precios |> 
  ggplot(aes(x = feha_d, y = precio_num)) +
    geom_point() +
    geom_smooth(method = 'loess', formula = 'y ~ x', span = 0.3) +
    labs(title = "Precio del limón sin semilla", 
         subtitle = "Xalapa, Ver. entre 1/ene/2025 y 1/abr/2025") +
    xlab(label = "Fecha") +
    ylab(label = "Precio ($ mn/kg)") +
    scale_x_date(labels = date_format("%b-%Y", locale = "es"))

Referencias

Castro, C. D. P. (2021). Usando R para jugar con los microdatos del INEGI. En tacosdedatos. https://bit.ly/3Fz35Vh
Escoto Castillo, A. R. (2021). ¿Cómo empezar a estudiar el mercado de trabajo en México? (Una introducción al análisis estadístico con R aplicado a la Encuesta Nacional de Ocupación y Empleo). UNAM. https://bit.ly/3XRrxYa
Giadrossich, F., Murgia, I., Guastini, E., Ganga, A., Di Prima, S., Chessa, L., Lovreglio, R., & Scotti, R. (2025). FAIR-Compliant Database for Soil Erosion Studies: The Marganai Forest Experiment. Scientific Data, 12(1). https://doi.org/10.1038/s41597-025-04797-0
Griffiths, E., Greci, C., Kotrotsios, Y., Parker, S., Scott, J., Welpton, R., Wolters, A., & Woods, C. (2020). Manual de Control de Divulgación Estadística de Resultados.