Introducción

Para realizar inferencias robustas utilizando los datos de eBird, es necesario procesar los datos de manera cuidadosa. Existen dos características que distinguen a Ebird de cualquier otro proyecto de ciencia ciudadana y los cuales facilitan análisis ecológicos robustos: la estructura de las listas permite la inferecia de las “no-detecciones” y la información del esfuerzo -asociada a cada lista- facilita diversos análisis para medir la magnitud de la variación durante el proceso de observación (La Sorte et al. 2018; Kelling et al. 2018). eBird es un projecto de ciencia ciudadana semi-estructurado, por lo que es flexible, con protocolos fáciles de seguir para atraer mas participantes, pero al mismo tiempo colectar datos durante el proceso de observación (ej: duración de la salida de observación, cantidad de observadores, etc.), los cuales pueden utilizarse durante los análisis (Kelling et al. 2018).

En este sentido, todos los análisis con datos de eBird estan asociados a las listas completas subidas por los observadores. Una lista completa es cualquier listado donde los observadores reportan todas las aves que fueron capaces de detectar e identificar, junto con los datos de esfuerzo. Esta estructura permite a investigadores inferir conteos de 0 individuos para las especies que no fueron reportadas en dicha lista. Esto es algo que con listados incompletos no es posible ya que no podemos saber con seguridad si la ausencia de una especie en la lista es una no-deteccion o el resultado de no haberla registrado.

Preparando el entorno

Antes de realizar cualquier análisis o trabajar con los datos, primero debemos instalar los paquetes necesarios para hacer funcionar los que estan relacionados con eBird. En la mayoría de los casos es suficiente con instalar el paquete “remotes” y el paquete “ebppackages”, pero puede ocurrir que la instalación de “ebppackages” no pueda realizarse debido a problemas con el repositorio. Estos problemas suelen estar relacionados con ausencia de ciertos paquetes en el repositorio y la única solución es instarlos previamente de manera manual. R nos indicará si existe algun error con la instalación de “remotes” o “ebppackages” y cuales son los paquetes que estan causando conflicto. Por otro lado, tengan en cuenta que para instalar la mayoria de estos paquetes es necesario tener previamente instalado Rtools en la computadora.

Muchas veces R nos arroja advertencias durante el proceso de instalación y esto también puede ocasionar la interrupción de la instalación, para solucionar esto es necesario correr primero la linea R_REMOTES_NO_ERRORS_FROM_WARNINGS=“true” y luego continuar con los demas pasos. Los siguientes paquetes deben instalarse antes de comenzar a trabajar directamente con los datos de eBird:

#Previene el error de instalación
#Sys.setenv(R_REMOTES_NO_ERRORS_FROM_WARNINGS="true")

#Paquetes a utilizar
# install.packages("sf")
# install.packages("remotes")
# install.packages("rnaturalearth")
# install.packages("dplyr")
# install.packages("lubridate")
# install.packages("gridExtra")
# devtools::install_github("zmjones/edarf", subdir = "pkg")
# devtools::install_github("hunzikp/velox")
# remotes::install_github('r-barnes/dggridR', vignette=TRUE, force = TRUE)
# remotes::install_github("mstrimas/ebppackages")

#Cargamos las librerías al entorno
library(ebppackages)
library(remotes)
library(sf)
library(rnaturalearth)
library(dplyr)
library(lubridate)
library(sf)
library(gridExtra)
library(tidyverse)

Obteniendo los datos de eBird

La base de datos de eBird puede descargarse desde el portal web y solicitando acceso a la misma. Te solicitaran algunos datos personales, así como el nombre de tu proyecto y una descripción del uso que se le dará a los datos. Una vez enviada la solicitud, la misma es evaluada por el Laboratorio Cornell de Ornitología y si es aprobada te notificarán al mail asociado a tu cuenta de eBird.

Una vez tengamos acceso, necesitamos descargar dos cosas: La base de datos básica de ebird (eBird Basic Dataset) y los datos de eventos de muestreo (Sampling Event Data). El primero contiene todos los datos de observaciones de eBird, mientras que el segundo contiene todos los datos asociados a las listas subidas a ebird.

Preparando los datos

Extracción de los datos de interés

La base de datos de eBird es inmensa -de ahora en mas EBD-, esto hace que trabajar con ella sea un desafío debido a su tamaño (cerca de 200 GB). Archivos de texto de este tamaño no pueden abrirse en la mayoria de programas como R o Excel. Afortunadamente, el paquete “auk” ha sido diseñado especificamente para extraer los datos contenidos en el EBD y manejarlos de una manera eficiente para su análisis, utilizando AWK. Tanto para poder utilizar AWK, así como para instalar el paquete “auk”, se deben seguir las instrucciones de instalación acá. Una vez instalado auk, cargamos el paquete al entorno de trabajo, indicamos la ruta de instalación del paquete “auk” y de AWK, y de la carpeta donde tenemos alojados el EBD y SED.

#Cargamos el paquete "auk"
library(auk)

#Set AWK path
auk::auk_set_awk_path(path = "D:/cygwin64/bin/gawk.exe", overwrite = T)
Sys.setenv(AWK_PATH= "D:/cygwin64/bin/gawk.exe")

# set ebd path and EBD directory
auk::auk_set_ebd_path(path = "D:/EbirdPy/Urban_birds/data", overwrite = T)

#Resolver el problema de espacios en los nombres
select <- dplyr::select
#dir.create("D:/EbirdPy/Urban_birds/data", showWarnings = FALSE)

Ahora ya podemos comenzar a trabajar!. Primero debemos filtrar el EBD y el SED (Sampling Event Data), lo cual requierede 3 pasos:

  • Primero debemos asociar el EBD y el SED
  • Luego definimos los filtros a utilizar
  • Por último, aplicamos los filtros y exportamos los datos para su posterior uso

Asociando el EBD y el SED

Primero tenemos que asociar ambos archivos con la función “auk_ebd()” y guardarla como una variable. Esto se hace pensando en crear una matríz de presencias/ausencias en el futuro y asegura que los mismos filtros se pasen para ambos archivos y de esta manera contengan los mismos datos relacionados con las listas. En este sentido es FUNDAMENTAL que ambos archivos sean del mismo periodo (release). Esto se puede verificar mirando la terminación en el nombre de los archivos: en este ejemplo son del periodo comprendido hasta Marzo 2020 (relMar-2020).

#Asociamos los dos archivos de texto
ebd <- auk_ebd("ebd_PY_relMar-2020.txt", 
               file_sampling = "ebd_sampling_relMar-2020.txt")

Definimos los filtros

A continuación definimos los filtros que queremos aplicar al EBD y al SED. Cada uno de los campos en los archivos de texto posee un filtro asociado en el paquete. Para filtrar las observaciones de una especie particular utilizamos auk_species(), con auk_date() definimos el intervalo de tiempo, y también podemos seleccionar observaciones dentro de algun protocolo particular con auk_protocol(). Retenemos solo las listas completas utilizando auk_complete() ya que queremos elaborar una matríz de presencias/ausencias. Para una descripción mas detallada de las funciones y filtros consultar la documentación de AUK.

#Definimos los filtros
ebd_filters <- ebd %>% 
  #Seleccionamos la especie, caso contrario los filtros se aplican a todas
  auk_species("Thraupis sayaca") %>% 
  # Seleccionar la localidad 
  #(para ver la codificación revisar ebird_states)
  auk_state(state = "PY-ASU") %>% 
  # 2000 a 2020, utilizar * para filtrar en todos los años
  auk_date(date = c("2000-01-01", "2020-03-31")) %>% 
  # restringir a observaciones con los protocolos mas rigurosos
  auk_protocol(protocol = c("Stationary", "Traveling")) %>% 
  auk_complete()

Filtrando los datos

Hasta acá solo definimos los filtros pero no los aplicamos aún al EBD. El último paso es utilziar auk_filter() para compilar los filtros en un script de AWK y correrlo para producir dos outputs: uno para el EBD y otro para el SED. Este paso puede durar tiempo (varias horas dependiendo del tamaño del EBD) por lo que es prudente colocar el codigo dentro de un condicional “if” para que solo se deba correr una vez. Usuarios de Windows necesitan tener instalado Cygwin para que este paso funcione (ver documentación de auk).

# output
data_dir <- "D:/EbirdPy/Urban_birds/data"
if (!dir.exists(data_dir)) {
  dir.create(data_dir)
}
f_ebd <- file.path(data_dir, "ebd_Sayaca.txt")
f_sampling <- file.path(data_dir, "sed_Sayaca.txt")

# only run if the files don't already exist
if (!file.exists(f_ebd)) {
  auk_filter(ebd_filters, file = f_ebd, file_sampling = f_sampling)
}

A través de todo el proceso de filtrado mantuvimos al EBD y al SED juntos gracias a la función auk_ebd() ya que es fundamental que los mismos filtros se apliquen a ambas bases de datos. Con estos pasos logramos obtener dos archivos de texto que pueden ser manejados para futuros análisis (como la generación de la matríz de presencias/ausencias), y los guardamos en la carpeta “data” en el directorio de trabajo.

Creando la matríz de P/A

Una vez filtrada la base de datos deberiamos tener dos archivos de texto delimitado por comas (.csv): uno de el EBD y otro del SED. Si pasamos directamente de la Parte 1 del tutorial a la Parte 2 durante la misma sesión de R entonces pasamos directamente a la generación de la matríz y podemos obviar esta parte, caso contrario primero debemos cargar todos los paquetes y establecer el entorno como lo hicimos previamente para que “auk” pueda funcionar.

Establecemos el entorno de trabajo nuevamente:

#Cargamos las librerías al entorno
library(ebppackages)
library(remotes)
library(sf)
library(rnaturalearth)
library(dplyr)
library(lubridate)
library(sf)
library(gridExtra)
library(tidyverse)
library(auk)


#Set AWK path
auk::auk_set_awk_path(path = "D:/cygwin64/bin/gawk.exe", overwrite = T)
Sys.setenv(AWK_PATH= "D:/cygwin64/bin/gawk.exe")

# set ebd path and EBD directory
auk::auk_set_ebd_path(path = "D:/EbirdPy/Urban_birds/data", overwrite = T)

#Resolver el problema de espacios en los nombres
select <- dplyr::select

Cargamos los archivos de texto guardados en nuestro directorio de trabajo:

#Le decimos a R donde buscar los archivos
data_dir <- "D:/EbirdPy/Urban_birds/data"

#Cargamos los archivos con los datos de la especie
f_ebd <- file.path(data_dir, "ebd_Sayaca.txt")
f_sampling <- file.path(data_dir, "sed_Sayaca.txt")

Debemos ejecutar lo anterior solo si comenzamos una nueva sesión en R, si la Parte 1 del tutorial forma parte de la misma sesión de R entonces pasamos directamente a la generación de la matríz. Para esto usamos auk_zerofill(), el cual nos permite leer estos dos archivos en R y los combina para crear una matriz de presencias/ausencias, datos de deteccion/no-deteccion. En el caso que querramos leer solo uno de los archivos usamos read_ebd() para el EBD o read_sampling() para el SED.

#creammos la matriz
ebd_zf <- auk_zerofill(f_ebd, f_sampling, collapse = TRUE)

últimos pasos y filtros adicionales

Primero tenemos que transformar algunas de las variables a un formato más útil para futuros análisis. Transformamos el “tiempo” a valores decimales entre 0 y 24, y forzamos la conversión de la distancia del recorrido a 0 cuando el protocolo es “stationary”. Es necesario tener en cuenta que los eBirders tienen la opción de ingresar “X” en vez del conteo de especies, para indicar que la especie estuvo presente pero que no realizaron el conteo de los individuos observados. Durante el modelado, nos gustaría que la variable “observation_count” este almacenada como “integer” por lo que convertiremos “X” a NA.

# Función que convierte la duración del recorrido a horas desde la medianoche
time_to_decimal <- function(x) {
  x <- hms(x, quiet = TRUE)
  hour(x) + minute(x) / 60 + second(x) / 3600
}

# Limpiamos las variables dentro de nuestro DF
ebd_zf <- ebd_zf %>% 
  mutate(
    # Convertimos X a NA
    observation_count = if_else(observation_count == "X", 
                                NA_character_, observation_count),
    observation_count = as.integer(observation_count),
    # effort_distance_km a 0 para conteos sin desplazamiento
    effort_distance_km = if_else(protocol_type != "Traveling", 
                                 0, effort_distance_km),
    # Convertimos tiempo a horas desde la media noche en formato decimal
    time_observations_started = time_to_decimal(time_observations_started),
    # Separamos fechas en año y día del año
    year = year(observation_date),
    day_of_year = yday(observation_date)
  )

La variación en el esfuerzo entre las distintas listas hace que realizar inferencias sea todo un desafío, esto se debe a su asociación con la variación de la detectabilidad. Cuando trabajamos con datos como los de eBird, una manera de lidiar con esta variación es imponer algún tipo de estructura mas consistente en los datos, filtrando las observaciones a partir de las variables de esfuerzo. Esto reduce la variación en la detectabilidad entre las listas. Se recomienda por lo general, con base a la experiencia de investigadores que ya han utilizado estos datos en otras partes del mundo, restringir a listas con menos de 5 horas de duración y 5 km de distancia recorrida, ademas de listas con 10 o menos observadores pero podrían utilizarse otros parámetros si el objetivo de tu trabajo lo requiere. En nuestro caso, ademas consideramos datos de los últimos 10 años.

# Filtrado adicional
ebd_zf_filtered <- ebd_zf %>% 
  filter(
    # Filtros de esfuerzo
    duration_minutes <= 5 * 60,
    effort_distance_km <= 5,
    # últimos 10 años de los datos
    year >= 2010,
    # 10 o menos observadores
    number_observers <= 10)

Para terminar, los datos en el EBD tienen varias variables que pueden considerarse como redundantes (Nombre de los departamentos de Paraguay y los códigos de los mismos) o innecesarios para realizar los modelos (ej: comentarios). En este punto podemos remover esas variables y retener solo aquellas que necesitamos para realizar los análisis y luego guardar los resultados para poder utilizarlos luego. Esto también queda a criterio de cada uno pues si consideramos necesarios algunos campos para analizarlos más adelante, podemos dejarlos.

ebird <- ebd_zf_filtered %>% 
  select(checklist_id, observer_id, sampling_event_identifier,
         scientific_name,
         observation_count, species_observed, 
         state_code, locality_id, latitude, longitude,
         protocol_type, all_species_reported,
         observation_date, year, day_of_year,
         time_observations_started, 
         duration_minutes, effort_distance_km,
         number_observers)
write_csv(ebird, "D:/EbirdPy/Urban_birds/data/ebd_thraupisSayaca_zf.csv", na = "")

Hasta acá la primera parte de este tutorial para el uso de los datos de eBird. El siguiente paso es utilizar el resultado final de esta parte para comenzar a hacer algunos análisis básicos con ellos como medir la variación de la detectabilidad de la especie o las franjas horarias de mayor actividad de observadores, de la especie entre otras cosas.

Si tienen alguna duda o quieren dar feedback pueden contactarme haciendo click acá