En el presente documento se expone, de manera detallada y basada en
el contexto de la Universidad Nacional de Colombia Sede La Paz, el
proceso completo para realizar un análisis de información biológica
geoespacial mediante el uso del software R. A lo largo del informe se
describe la lectura, tratamiento y conversión de bases de datos
provenientes de archivos en formatos .xlsx,
.csv y .shp, así como la construcción de
objetos espaciales que permiten estructurar adecuadamente los datos para
su representación cartográfica. De igual manera, se presenta la forma en
que se elaboran mapas de observaciones, mapas de calor y
representaciones temáticas basadas en índices de diversidad, utilizando
herramientas como sf, dplyr,
leaflet y vegan. Adicionalmente, se desarrolla
la división del espacio geográfico en cuadrículas, la creación de
matrices de abundancia y ausencia-presencia y el cálculo de los índices
de Shannon y Simpson, todo ello con el fin de ilustrar una ruta
metodológica clara que facilite la comprensión, visualización y análisis
de la distribución espacial de las aves en el campus universitario. En
síntesis, este documento tiene como propósito servir como una guía
práctica y pedagógica que permita a los lectores familiarizarse con el
manejo de información georreferenciada en R y con la generación de
productos analíticos y cartográficos aplicados al estudio de la
biodiversidad.
Previo a empezar, se recomienda tener la última versión de R instalada R 4.5.1.
Para el procesamiento y el análisis de los datos, sera necesario utilizar los siguientes paquetes:
## Linking to GEOS 3.11.2, GDAL 3.8.2, PROJ 9.3.1; sf_use_s2() is TRUE
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
##
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
## Loading required package: viridisLite
## Loading required package: permute
## Loading required package: lattice
## This is vegan 2.6-6.1
Obsérvese que la lectura de un paquete se realiza con la función
library() y en caso de que aparezca el siguiente error
Error: no se encontró la librería 'nombre_paquete', el cual
indica que el paquete bajo el nombre nombre_paquete no está
instalado, puede proceder instalándolo con la siguiente línea de código
install.package("nombre_paquete").
Una vez realizada la lectura de los paquetes, se procede a realizar la importación o lectura de la base de datos. Considerando en este caso que no solo se cuenta con el archivo que contiene los datos del levantamiento, sino que además, se necesitan archivos de la capa base (ya sea poligonos o raster) para la proyección del mapa del campus universitario UNAL; entonces la importación se realizará para ambos archivos.
Consideremos que el archivo en el cual se encuentran los datos esta
un formato .xlsx (es decir, un archivo excel), se utilizará la
función read_excel() para la importación como se muestra a
continuación:
ruta <- "C:\\Users\\brial\\OneDrive\\Documentos\\Avistamiento_Aves\\"
aves <- read_excel(paste(ruta,"Simulados_datos.xlsx", sep=""),
sheet = "Hoja3") Cabe mencionar, que la ruta debe ajustarse según donde tenga guardado su archivo.
Considere ahora que su archivo de datos sobre el avistamiento de aves
no se encuentra en un archivo .xlsx sino en un archivo
.csv, entonces la indicación es utilizar la función
read.csv() adecuada para esta situación. A continuación, un
ejemplo:
Note que esta función posee el parametro sep = ";" lo
que indica que nuestro archivo esta separado por el signo “;”; por lo
cual, usted deberá ajustar este parametro según requiera (por ejemplo:
“,”, “_“,”-“,”@“,…).
Una vez realizada la lectura de la base de datos, se procederá con un tratamiento sencillo para mostrar un ejemplo sencillo de cómo tratar su base de datos una vez cargada al programa R.
aves <- aves %>%
select(decimalLongitude, decimalLatitude, scientificName, cantidad) %>%
mutate(
longitud = as.numeric(decimalLongitude),
latitud = as.numeric(decimalLatitude)
) %>%
filter(!is.na(latitud), !is.na(longitud))
aves_filtro <- aves %>%
select(decimalLatitude, scientificName, cantidad) %>%
mutate(
latitud = as.numeric(decimalLatitude)
) %>%
group_by(scientificName) %>%
summarise(Total_individuos = sum(cantidad, na.rm = TRUE)) %>%
filter((scientificName == "Colinus cristatus" |
scientificName == "Eupsittula pertinax" |
scientificName == "Falco sparverius"
) &
Total_individuos >= 3)En este caso, el paquete dplyr permite ejecutar varias
acciones a una base de datos y generar una nueva con todo el tratamiento
realizado, esto lo realiza con ayuda del operador %>%.
En el código mostrado anteriormente para generar la tabla
aves_filtro permite seleccionar en primer lugar las columnas
que se deseen, en segundo lugar, agregar nuevas columnas, en tercer
lugar, agrupar y resumir los datos agrupados sumandolos, en cuarto
lugar, filtrar los datos cuantas veces desee.
Ahora bien, para el caso del polígono que delimita el área del campus
universitario, se requiere la lectura de un archivo en formato
.shp, el cual es un formato de archivo de datos vectoriales
para Sistemas de Información Geográfica (SIG), de manera que, si se
desea hacer mapas en R, un paquete útil y estándar en el manejo de este
tipo de archivos es el paquete sf (simple features), que
facilita el trabajo con los datos geográficos, proporcionando una
integración más sencilla y directa con los objetos de R.
De manera que la lectura del polígono será realizada con la función
st_read() del paquete mencionado anteriormente
(sf).
campus <- st_read(paste(ruta,"campus_unal.shp", sep=""), quiet = TRUE) %>%
st_transform(4326) %>%
st_make_valid()Observe que en este caso a la función de la lectura del shapefile
(.shp) se le agregan las funciones st_transform(4326)
y st_make_valid(), donde la primera permitirá transformar
el sistema de coordenadas del objeto espacial para mostrar el mapa
correctamente en visores como Leaflet, Google Maps o
OpenStreetMap; y la segunda función, aumenta la garantía de que
las geometrías cumplan con los estándares espaciales, pues algunos
shapefiles tienen geometrías inválidas.
En este paso, se convierte la base de datos previamente cargada a un
objeto espacial, lo cual permite trabajarla en un entorno geográfico.
Para ello, se utiliza la función st_as_sf() del paquete sf,
que transforma un data frame convencional en un objeto espacial con
coordenadas geográficas definidas.
El argumento coords = c("longitud", "latitud") indica
las columnas donde se encuentran las coordenadas, mientras que
crs = 4326 establece el sistema de referencia espacial WGS
84, utilizado de manera estándar en plataformas como Google Maps y
OpenStreetMap. Por su parte, remove = FALSE conserva las
columnas originales de coordenadas dentro del nuevo objeto espacial,
evitando su eliminación tras la conversión.
Una vez definidos los puntos espaciales, se procede a filtrar
aquellos que se encuentren dentro del polígono que delimita el campus
universitario. Esta operación se realiza mediante la función
st_within(), que permite seleccionar únicamente los
registros ubicados dentro del área de interés.
De esta manera, se garantiza que el análisis posterior se concentre exclusivamente en los datos correspondientes al ámbito espacial del estudio.
A continuación, se presentan diferentes representaciones cartográficas que permiten visualizar la distribución espacial de las aves registradas dentro del campus universitario, utilizando el paquete leaflet, que facilita la creación de mapas interactivos.
El primer mapa muestra los puntos de observación de aves sobre una
imagen satelital del campus. En este caso, se utiliza la función
addCircleMarkers() para representar cada registro con un
marcador circular.
leaflet() %>%
addProviderTiles("Esri.WorldImagery") %>%
addPolygons(data = campus, fillColor = "transparent", color = "red", weight = 2) %>%
addCircleMarkers(
lng = aves.sf$longitud,
lat = aves.sf$latitud,
radius = 5,
color = "orange",
stroke = FALSE,
fillOpacity = 0.7,
popup = paste0(
"<b>Nombre:</b> ", aves.sf$scientificName, "<br>",
"<b>Coordenada:</b> ", aves.sf$longitud, ";", aves.sf$latitud, "<br>"
)
)Cada marcador incluye un popup informativo con el nombre científico de la especie y su localización. Esta visualización permite identificar las zonas del campus con mayor concentración de observaciones.
En esta segunda representación, se genera un mapa de calor que
permite identificar visualmente las zonas con mayor intensidad de
observaciones. Para ello, se emplea la función
addHeatmap(), la cual utiliza los valores de cantidad de
individuos como ponderador.
leaflet() %>%
addProviderTiles("Esri.WorldImagery") %>%
addPolygons(data = campus, fillColor = "transparent", color = "red", weight = 2) %>%
addHeatmap(
lng = aves.sf$longitud,
lat = aves.sf$latitud,
intensity = aves.sf$cantidad * 3,
radius = 50, blur = 20,
max = max(aves.sf$cantidad, na.rm = TRUE),
gradient = c(
"0.0" = "transparent",
"0.2" = "skyblue",
"0.4" = "limegreen",
"0.6" = "yellow",
"0.8" = "orange",
"1.0" = "red"
)
)En este mapa, los colores más cálidos (amarillos y rojos) representan áreas con mayor número de registros o abundancia, mientras que las zonas frías indican menor actividad observada.
# Convertir a proyección métrica (UTM zona 18N)
campus_utm <- st_transform(campus, 32618)
aves_sf_utm <- st_transform(aves.sf, 32618)
# Crear una cuadrícula de 100 m dentro del campus
grid <- st_make_grid(campus_utm, cellsize = 100, square = TRUE)
grid_sf <- st_sf(ID = 1:length(grid), geometry = grid)
grid_campus <- st_intersection(grid_sf, campus_utm)## Warning: attribute variables are assumed to be spatially constant throughout
## all geometries
tabla_abundancia <- aves_join %>%
st_drop_geometry() %>%
group_by(ID, scientificName) %>%
summarise(Total_individuos = sum(cantidad, na.rm = TRUE)) %>%
ungroup() %>%
pivot_wider(names_from = scientificName,
values_from = Total_individuos,
values_fill = 0)## `summarise()` has grouped output by 'ID'. You can override using the `.groups`
## argument.
Estos índices permiten cuantificar la diversidad de especies dentro de cada cuadrícula definida en el campus. El índice de Shannon mide la abundancia y equidad de las especies, mientras que el índice de Simpson evalúa la probabilidad de que dos individuos seleccionados al azar pertenezcan a la misma especie. Ambos proporcionan una visión integral de la composición ecológica.
diversidad_indices <- tabla_abundancia %>%
mutate(
Shannon = diversity(select(., -ID), index = "shannon"),
Simpson = diversity(select(., -ID), index = "simpson")
) %>%
select(ID, Shannon, Simpson)En este fragmento, la función diversity() del paquete
vegan calcula ambos índices a partir de la matriz de abundancia,
excluyendo la columna ID mediante
select(., -ID) para operar únicamente sobre las
especies.
Una vez obtenidos los índices, es necesario integrarlos con la capa espacial que representa las celdas del campus, para así visualizar la distribución espacial de la diversidad.
El uso de left_join() permite mantener todas las celdas
del campus, asociando los valores de Shannon y Simpson según su
identificador (ID). Finalmente, st_transform(4326) ajusta
el sistema de coordenadas para garantizar la compatibilidad con visores
geográficos.
Para representar los valores obtenidos, se genera un mapa temático utilizando la paleta viridis, la cual ofrece una escala perceptualmente uniforme y adecuada para interpretación visual.
pal_shannon <- colorNumeric("viridis", domain = diversidad_sf$Shannon)
leaflet(diversidad_sf) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(
fillColor = ~pal_shannon(Shannon),
color = "grey40",
weight = 1,
fillOpacity = 0.7,
label = ~paste0("Shannon: ", round(Shannon, 2))
) %>%
addLegend(pal = pal_shannon, values = diversidad_sf$Shannon,
title = "Índice de Shannon") %>%
addPolygons(data = campus, fill = NA, color = "black", weight = 1.5)En este código, cada celda se colorea según su valor de diversidad.
La función addLegend() agrega una escala interpretativa al
mapa, facilitando la comparación entre áreas. La capa final resalta los
límites del campus para contextualizar espacialmente los resultados.
Finalmente, se representa el índice de Simpson, el cual mide la probabilidad de que dos individuos seleccionados al azar dentro de una muestra pertenezcan a la misma especie. A diferencia del índice de Shannon, este indicador otorga un mayor peso a las especies dominantes, por lo que valores bajos reflejan una alta diversidad y valores altos indican dominancia de pocas especies.
pal_simpson <- colorNumeric("magma", domain = diversidad_sf$Simpson)
leaflet(diversidad_sf) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(
fillColor = ~pal_simpson(Simpson),
color = "grey40",
weight = 1,
fillOpacity = 0.7,
label = ~paste0("Simpson: ", round(Simpson, 2))
) %>%
addLegend(pal = pal_simpson, values = diversidad_sf$Simpson,
title = "Índice de Simpson") %>%
addPolygons(data = campus, fill = NA, color = "black", weight = 1.5)En este caso, la paleta “magma” permite resaltar las variaciones en
los valores del índice de forma visualmente armónica. La función
addLegend() agrega una escala que facilita la
interpretación de los resultados, mientras que
addPolygons() refuerza los límites del campus universitario
para mantener el contexto espacial de la representación.