Además de realizar consultas sobre las delimitaciones
político-administrativas oficiales del Perú (distritos y provincias),
peruocc ofrece la función
buscar_especies_poligono().
Esta utilidad permite delimitar áreas de estudio independientes,
tales como: * Polígonos de muestreo de campo y cuadrantes de inventario.
* Áreas Naturales Protegidas (ANP), concesiones forestales o zonas de
amortiguamiento. * Áreas de influencia directa/indirecta (buffers) de
proyectos ambientales. * Archivos espaciales en formatos estándar
(.shp, .geojson, .gpkg,
.kml).
Cargamos peruocc y sf para el manejo de
geometrías vectoriales:
library(peruocc)
#> ── Cargando peruocc ────────────────────────────────────────────────── v0.1.0 ──
#> ✔ geoperu 0.0.2 • Límites cartográficos oficiales del Perú
#> ✔ rgbif 3.8.5 • Extracción de ocurrencias desde GBIF
#> ✔ rinat 0.1.10 • Observaciones ciudadanas de iNaturalist
#> ✔ sf 1.1.2 • Operaciones geométricas y filtros espaciales
library(sf)
library(ggplot2)Podemos definir cualquier geometría poligonal en R. En este ejemplo, creamos un polígono rectangular de interés biológico en la costa central del Perú (alrededor de los humedales y costa de Lima):
# Coordenadas de los vértices del polígono (WGS84: Longitud, Latitud)
coordenadas <- matrix(
c(
-77.04, -12.06,
-77.00, -12.06,
-77.00, -12.02,
-77.04, -12.02,
-77.04, -12.06
),
ncol = 2,
byrow = TRUE
)
# Construir el objeto sf con proyección geográfica EPSG:4326 (WGS84)
mi_zona_estudio <- sf::st_as_sf(
sf::st_sfc(sf::st_polygon(list(coordenadas)), crs = 4326)
)
print(mi_zona_estudio)
#> Simple feature collection with 1 feature and 0 fields
#> Geometry type: POLYGON
#> Dimension: XY
#> Bounding box: xmin: -77.04 ymin: -12.06 xmax: -77 ymax: -12.02
#> Geodetic CRS: WGS 84
#> x
#> 1 POLYGON ((-77.04 -12.06, -7...buscar_especies_poligono()Ejecutamos la búsqueda de flora dentro del polígono creado.
peruocc gestiona automáticamente: 1. La consulta síncrona a
GBIF con simplificación adaptativa WKT en UTM. 2. La
consulta a iNaturalist por Bounding Box. 3. El
recorte espacial exacto en memoria
(sf::st_intersects) para asegurar que cada punto
caiga estrictamente dentro de la geometría. 4. La estandarización y
deduplicación bajo el estándar Darwin Core.
resultado_personalizado <- buscar_especies_poligono(
poligono = mi_zona_estudio,
nombre = "Area_Estudio_Costa",
grupo = "flora",
limite_por_api = 25
)
#>
#> ── Búsqueda Integrada en Polígono: AREA_ESTUDIO_COSTA ──────────────────────────
#> • Grupo: flora
#> ℹ [GBIF] Iniciando búsqueda de ocurrencias...
#> ℹ [GBIF] Filtrando por reino Plantae (Flora).
#> ℹ [GBIF] Consultando registros dentro del polígono de Unidad seleccionada (límite: "25")...
#> ✔ [GBIF] Búsqueda finalizada. Se filtraron 25 registro(s) que caen dentro del polígono seleccionado.
#> ℹ [iNaturalist] Iniciando búsqueda de ocurrencias...
#> ℹ [iNaturalist] Filtrando por reino Plantae (Flora).
#> ℹ [iNaturalist] Consultando registros dentro de la caja delimitadora de Unidad seleccionada (límite: "25")...
#> ℹ [iNaturalist] Se descargaron 25 registros en la caja delimitadora. Aplicando filtro espacial...
#> ✔ [iNaturalist] Búsqueda finalizada. 25 de 25 registros caen dentro del polígono seleccionado.
#> ✔ Consolidación exitosa. Total de registros unificados: 50
#>
#> ── Resumen de Registros ──
#>
#> • GBIF: 25 registro(s)
#> • iNaturalist: 25 registro(s)
#> ✔ Total consolidado: 50 registro(s)El objeto devuelto contiene la estructura estándar de
peruocc:
# Resumen de registros por base de datos
print(resultado_personalizado$resumen)
#> $nivel
#> [1] "poligono"
#>
#> $unidad
#> [1] "Area_Estudio_Costa"
#>
#> $distrito
#> [1] NA
#>
#> $provincia
#> [1] NA
#>
#> $departamento
#> [1] NA
#>
#> $total_registros
#> [1] 50
#>
#> $registros_gbif
#> [1] 25
#>
#> $registros_inat
#> [1] 25
#>
#> $limite_por_api
#> [1] 25
#>
#> $gbif_total_reportado_api
#> [1] NA
#>
#> $inat_total_reportado_api
#> [1] NA
#>
#> $gbif_descarga_completa_api
#> [1] FALSE
#>
#> $inat_descarga_completa_api
#> [1] FALSE
#>
#> $lotes_espaciales
#> [1] 1
#>
#> $fallos_lotes
#> character(0)
#>
#> $nota_cobertura
#> [1] "Se solicito una muestra limitada por API; la cobertura puede estar truncada."
# Vista previa de las primeras ocurrencias
head(resultado_personalizado$ocurrencias[, c("scientificName", "source", "eventDate", "decimalLatitude", "decimalLongitude")])
#> # A tibble: 6 × 5
#> scientificName source eventDate decimalLatitude decimalLongitude
#> <chr> <chr> <chr> <dbl> <dbl>
#> 1 Washingtonia … GBIF 2026-04-… -12.1 -77.0
#> 2 Fragaria vesc… GBIF 2025-05-… -12.0 -77.0
#> 3 Annona cherim… GBIF 2025-05-… -12.0 -77.0
#> 4 Passiflora ed… GBIF 2025-06-… -12.0 -77.0
#> 5 Urtica urens … GBIF 2025-08-… -12.1 -77.0
#> 6 Sonchus asper… GBIF 2025-10-… -12.1 -77.0graficar_ocurrencias()Podemos generar composiciones en ggplot2 superponiendo
el polígono con las observaciones:
Un escenario común en consultoría ambiental y monitoreo biológico es evaluar la biodiversidad en un radio o buffer de influencia alrededor de un punto de coordenadas (por ejemplo, una estación biológica o sitio arqueológico en Cusco):
# 1. Definir coordenadas del punto central (WGS84: Longitud, Latitud)
punto_sitio <- sf::st_sfc(sf::st_point(c(-72.545, -13.163)), crs = 4326) # Valle de Urubamba / Machu Picchu
# 2. Proyectar a UTM Zona 18S (EPSG:32718) para calcular un buffer métrico exacto de 3 km
buffer_3km <- sf::st_buffer(sf::st_transform(punto_sitio, 32718), dist = 3000)
# 3. Consultar directamente (peruocc retransforma automáticamente a WGS84)
# resultado_buffer <- buscar_especies_poligono(
# poligono = buffer_3km,
# nombre = "Buffer_3km_Urubamba",
# grupo = "flora",
# limite_por_api = 50
# )peruocc detecta cualquier sistema de referencia de
coordenadas (CRS proyectado o geográfico), repara topologías no válidas
(sf::st_make_valid) y asegura la orientación antihoraria
(CCW) antes de la consulta a las APIs.
buscar_especies_poligono() también acepta directamente
una ruta a un archivo espacial en disco (.shp,
.geojson, .gpkg o .kml).
Para demostrarlo, guardamos el polígono en un archivo
.geojson y ejecutamos la consulta directamente desde la
ruta:
# 1. Guardar el polígono temporalmente como archivo GeoJSON
ruta_capa <- file.path(tempdir(), "mi_reserva.geojson")
sf::st_write(mi_zona_estudio, ruta_capa, quiet = TRUE, delete_dsn = TRUE)
# 2. Consultar directamente pasando la ruta del archivo
resultado_desde_archivo <- buscar_especies_poligono(
poligono = ruta_capa,
nombre = "Reserva_Local",
grupo = "flora",
limite_por_api = 15
)
#>
#> ── Búsqueda Integrada en Polígono: RESERVA_LOCAL ───────────────────────────────
#> • Grupo: flora
#> ℹ [GBIF] Iniciando búsqueda de ocurrencias...
#> ℹ [GBIF] Filtrando por reino Plantae (Flora).
#> ℹ [GBIF] Consultando registros dentro del polígono de Unidad seleccionada (límite: "15")...
#> ✔ [GBIF] Búsqueda finalizada. Se filtraron 15 registro(s) que caen dentro del polígono seleccionado.
#> ℹ [iNaturalist] Iniciando búsqueda de ocurrencias...
#> ℹ [iNaturalist] Filtrando por reino Plantae (Flora).
#> ℹ [iNaturalist] Consultando registros dentro de la caja delimitadora de Unidad seleccionada (límite: "15")...
#> ℹ [iNaturalist] Se descargaron 15 registros en la caja delimitadora. Aplicando filtro espacial...
#> ✔ [iNaturalist] Búsqueda finalizada. 15 de 15 registros caen dentro del polígono seleccionado.
#> ✔ Consolidación exitosa. Total de registros unificados: 30
#>
#> ── Resumen de Registros ──
#>
#> • GBIF: 15 registro(s)
#> • iNaturalist: 15 registro(s)
#> ✔ Total consolidado: 30 registro(s)
# 3. Exportar resultados con manifiesto de reproducibilidad en directorio temporal
archivos_exportados <- exportar_resultados(resultado_desde_archivo, dir_salida = tempdir())
#> ✔ Registros tabulares guardados en: 'C:\Users\PC\AppData\Local\Temp\RtmpCQLgeB/ocurrencias_20260911T030410Z_poligono_reservalocal_flora.csv'
#> ✔ Capa espacial GeoJSON guardada en: 'C:\Users\PC\AppData\Local\Temp\RtmpCQLgeB/ocurrencias_20260911T030410Z_poligono_reservalocal_flora.geojson'
#> ✔ Manifiesto JSON guardado en: 'C:\Users\PC\AppData\Local\Temp\RtmpCQLgeB/manifiesto_20260911T030410Z_poligono_reservalocal_flora.json'