Skip to contents

Introducción

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).


1. Carga de Librerías y Configuración

Cargamos peruocc y sf para el manejo de geometrías vectoriales:

library(peruocc)
#> ── Cargando peruocc ────────────────────────────────────────────────── v0.1.0 ──
#>  geoperu 0.0.1   • 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)

2. Creación de un Polígono de Estudio Personalizado

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...

3. Consulta Integrada de Biodiversidad: 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)

4. Inspección de los Resultados Obtenidos

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.0

5. Visualización Cartográfica con graficar_ocurrencias()

Podemos generar composiciones en ggplot2 superponiendo el polígono con las observaciones:

A. Clasificación por Proveedor de Datos (GBIF vs iNaturalist)

mapa_fuentes <- graficar_ocurrencias(
  resultado_lista = resultado_personalizado,
  color_por = "source"
)

print(mapa_fuentes)

Mapa de distribución de ocurrencias de flora en área de estudio personalizada coloreado por repositorio de origen (GBIF vs iNaturalist)

B. Clasificación por Reino Taxonómico

mapa_reinos <- graficar_ocurrencias(
  resultado_lista = resultado_personalizado,
  color_por = "kingdom"
)

print(mapa_reinos)

Mapa de distribución de ocurrencias de flora en área de estudio personalizada coloreado por reino taxonómico


6. Caso Práctico: Área de Influencia / Buffer Alrededor de un Sitio de Muestreo

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.


7. Consulta desde un Archivo en Disco (Shapefile / GeoJSON)

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: /tmp/RtmpalcRIP/ocurrencias_20260911T030604Z_poligono_reservalocal_flora.csv
#>  Capa espacial GeoJSON guardada en: /tmp/RtmpalcRIP/ocurrencias_20260911T030604Z_poligono_reservalocal_flora.geojson
#>  Manifiesto JSON guardado en: /tmp/RtmpalcRIP/manifiesto_20260911T030604Z_poligono_reservalocal_flora.json

Siguientes Pasos