Rock Pool Project Team Bioblitz - Autumn 2023

We are had a competition to record as many species as possible over the weekend of the 30th Sept/1st Oct. This weekend included team rock pooling events in Falmouth and Plymouth, but participants were able to record data over the whole weekend.

As well as this collective challenge, we were competing against each other in three separate teams:

All data were recorded via Inaturalist, a world leading biodiversity data submission hub, which provides the facility to record data together as ‘projects’. For this team bioblitz challenge we structured the three teams into three seperate project (links in bullet points above) and colated all three projects together under an umberella project called ‘The Rock Pool Project Team Bioblitz’. This allows inaturalist to present key results such as how many records and species have been recorded, both overall and per team.

Another key advantage of inaturalist is it’s community approach to data verification. This is important as we want our data to be as accurate as possible, while minimising technical complications for participants. We decided that we should aim for all records to achieve inaturalists ‘Research Grade’ category and to work together as a community to achieve this. We set a deadline of 10pm the Wednesday after the bioblitz challenge to finish verification and downloaded all the data at this point.

Before the event we decided that there would be awards for the following:

Inaturalist provides some of this information but only based on all the records collects, not specifically for records that were verified to Research Grade status. This code will subset the bioblitz data to just the research grade records and then determine the winners of these awards, as well as the overall results, based on these records.

The analysis and data are available from the Rock Pool Project github account here.

Firstly load in the data

#load in data
RPP_bioblitz_data <- read.csv("observations-363726.csv") #downloaded on the 5th October 2023

#subset to research grade

RPP_bioblitz_data_RG <- subset(RPP_bioblitz_data, quality_grade == "research")

Overall results

Before we work out who won the awards let’s see how many research grade records we collected and how many species they reported:

nrow(RPP_bioblitz_data_RG) #total number of records
## [1] 384
length(unique(RPP_bioblitz_data_RG$scientific_name)) #number of species
## [1] 202
length(unique(RPP_bioblitz_data_RG$user_name)) #number of conributors 
## [1] 13

So we have 384 research grade records for a total of 202 species, collected by 13 different people. What an amazing effort! Well done everyone!

Individual results

#most records
ind_rec_num <- sort(table(RPP_bioblitz_data_RG$user_login), decreasing = T) #a table of how many records per person

#most species
ind_sp_num <- rep(0, length(ind_rec_num)) #make a blank result object
names(ind_sp_num) <- names(ind_rec_num) #add the participant names

#loop through each person a record how many species they found

for (p in names(ind_sp_num)) {
  
  p_res <- subset(RPP_bioblitz_data_RG, user_login == p)
  
  ind_sp_num[p] <- length(unique(p_res$scientific_name))
  
    
}

#unique species records

recs_per_species <- table(RPP_bioblitz_data_RG$scientific_name) #table of the number of records for each species
unique_species <- names(recs_per_species)[recs_per_species == 1] # vector of just the species with only one record

RPP_bioblitz_data_RG_unique <- subset(RPP_bioblitz_data_RG, scientific_name %in% unique_species) # subset the data based on the species only recorded once

#most unique records

ind_rec_num_unique <- sort(table(RPP_bioblitz_data_RG_unique$user_login), decreasing = T) #a table of how many records per person for the unique species records

#combine all these results into a single table
ind_rec_num_unique <- ind_rec_num_unique[names(ind_sp_num)] #sort to match other results
names(ind_rec_num_unique) <- names(ind_rec_num)
ind_rec_num_unique[is.na(ind_rec_num_unique)] <- 0 #replace NAs with zeros



ind_res <- cbind("Records" = ind_rec_num, "Species" = ind_sp_num, "Unique Species" = ind_rec_num_unique)

library(DT)
## Warning: package 'DT' was built under R version 4.2.2
datatable(ind_res)%>% formatStyle(
  'Records',
  backgroundColor = styleEqual(sort(ind_rec_num, dec = T)[1:3], c('gold', 'gray', rgb(205, 127, 50, maxColorValue =  255)))
)%>% formatStyle(
  'Species',
  backgroundColor = styleEqual(sort(ind_sp_num, dec = T)[1:3], c('gold', 'gray', rgb(205, 127, 50, maxColorValue =  255)))
)%>% formatStyle(
  'Unique Species',
  backgroundColor = styleEqual(sort(ind_rec_num_unique, dec = T)[1:3], c('gold', 'gray', rgb(205, 127, 50, maxColorValue =  255)))
)

Many congratulations to Rebecca Bowyer for taking gold medal for the most records and also the most species, with an incredible 93 records and 77 species. Cath Francis and Jen Sutton takes silver and bronze respectively in both these categories. These three also shared the medals in the ‘Most Unique Species’ category, with Jen nipping in front of Rebecca for gold, finding 29 species that nobody else recorded. Without doubt three nature recording superstars!

Honourable mentions also goes to Team Plymouth’s top recorder Zak Russell, Amy Borland who provided the Rock Pool Project most northerly records to date from Orkney and Alan Smith providing the Rock Pool Projects most southerly records to date from the UAE!

Team results

The main inaturalist download does not provide data on which record belong to which team (or inaturalist project). So each team’s data need to be re-downloaded separately and loaded in:

#load in data
Fal_bioblitz_data <- read.csv("observations-363831.csv") #downloaded on the 5th October 2023
Ply_bioblitz_data <- read.csv("observations-363870.csv") #downloaded on the 5th October 2023
RoW_bioblitz_data <- read.csv("observations-363833.csv") #downloaded on the 5th October 2023

#subset the research grade data

Fal_bioblitz_data_RG <- subset(RPP_bioblitz_data_RG, user_login %in% Fal_bioblitz_data$user_login)
Ply_bioblitz_data_RG <- subset(RPP_bioblitz_data_RG, user_login %in% Ply_bioblitz_data$user_login)
RoW_bioblitz_data_RG <- subset(RPP_bioblitz_data_RG, user_login %in% RoW_bioblitz_data$user_login)

#check the team data matches up with the overall data
sum(c(nrow(Fal_bioblitz_data_RG),nrow(Ply_bioblitz_data_RG),nrow(RoW_bioblitz_data_RG))) == nrow(RPP_bioblitz_data_RG)
## [1] TRUE
#add team attribute column
RPP_bioblitz_data_RG$Team <- "Falmouth"
RPP_bioblitz_data_RG$Team[RPP_bioblitz_data_RG$user_login %in% Ply_bioblitz_data$user_login] <- "Plymouth"
RPP_bioblitz_data_RG$Team[RPP_bioblitz_data_RG$user_login %in% RoW_bioblitz_data_RG$user_login] <- "Rest of the World"
#most records
barplot(sort(table(RPP_bioblitz_data_RG$Team), decreasing = T), col = c('gold', 'gray', rgb(205, 127, 50, maxColorValue =  255)), main = "Research Grade Records")

#most species
team_sp_num <- rep(0, 3) #make a blank result object
names(team_sp_num) <- unique(RPP_bioblitz_data_RG$Team) #add the team names

#loop through each person a record how many species they found

for (i in names(team_sp_num)) {

   team_sp_num[i] <- length(unique(subset(RPP_bioblitz_data_RG, Team == i)$scientific_name))
    
}

barplot(sort(team_sp_num, decreasing = T), col = c('gold', 'gray', rgb(205, 127, 50, maxColorValue =  255)), main = "Research Grade Species")

#unique species
team_u_sp_num <- rep(0, 3) #make a blank result object
names(team_u_sp_num) <- unique(RPP_bioblitz_data_RG$Team) #add the team names

RPP_bioblitz_data_RG_unique <- subset(RPP_bioblitz_data_RG, scientific_name %in% unique_species) # redo this object to include team names

#loop through each person a record how many species they found

for (i in names(team_u_sp_num)) {

   team_u_sp_num[i] <- length(subset(RPP_bioblitz_data_RG_unique, Team == i)$scientific_name)
    
}

barplot(sort(team_u_sp_num, decreasing = T), col = c('gold', 'gray', rgb(205, 127, 50, maxColorValue =  255)), main = "Research Grade Unique Species")

Other awards

We also discussed two other awards: best species and best picture. Best picture can only be a subjective decision. We can download all the image for the research grade records and share them to allow people to vote.

Best picture

dir.create("Images")
## Warning in dir.create("Images"): 'Images' already exists
library(exifr)
## Using ExifTool version 12.22
record_ids <- RPP_bioblitz_data_RG$id

images_already_downloaded <- list.files("Images")

all_im_file_names <- paste0(paste(RPP_bioblitz_data_RG$common_name,RPP_bioblitz_data_RG$scientific_name, RPP_bioblitz_data_RG$user_login, sep = " - "),".jpg")

records_with_images_not_downloaded <- all_im_file_names[!all_im_file_names %in% images_already_downloaded]


for(i in records_with_images_not_downloaded){
  im_dat <- subset(RPP_bioblitz_data_RG, id == i)
  image_url <- im_dat$image_url
  
  image_dest <- paste0("Images/", paste(im_dat$common_name,im_dat$scientific_name, im_dat$user_login, sep = " - "),".jpg")
  try(download.file(image_url, image_dest, mode = "wb"))
  
}
## Error in download.file(image_url, image_dest, mode = "wb") : 
##   'url' must be a length-one character vector
## Error in download.file(image_url, image_dest, mode = "wb") : 
##   'url' must be a length-one character vector
## Error in download.file(image_url, image_dest, mode = "wb") : 
##   'url' must be a length-one character vector
## Error in download.file(image_url, image_dest, mode = "wb") : 
##   'url' must be a length-one character vector

I’ve uploaded these images to the Rock Pool Project FlickR account here.

My personal favourite is this one from Vicky Barlow:

blue rayed limpets

Best species

One way to determine the ‘best species’ is to base this decision on the species with the fewest current records on inaturalist. There is an R package called rinat that provides an interface with inaturalist and can obtain this information by downloading all the records for a specifiied species. These results can be subsetted by location but for this challenge I will just base this analysis on total number of observations across the world, since we do have records from all over the world.

library(rinat)
## Warning: package 'rinat' was built under R version 4.2.3
RPP_RG_spp <- unique(RPP_bioblitz_data_RG$scientific_name)

load("sp_inat_rec_num") #previously generated results

#any species not currently included?

missing_sp <- RPP_RG_spp[!RPP_RG_spp %in% names(sp_inat_rec_num)]

if (length(missing_sp) > 0) { #add missing species to results
sp_inat_rec_num_missing <- rep(0, length(missing_sp))
names(sp_inat_rec_num_missing) <- missing_sp
  sp_inat_rec_num <- c(sp_inat_rec_num, sp_inat_rec_num_missing)
  
  for (sp in missing_sp) {
  print(which(RPP_RG_spp == sp)/length(RPP_RG_spp))
  
  inat_search <- try(sp_inat_rec_num[sp] <- get_inat_obs(sp, maxresults = 10, meta = T)$meta$found)

  if(!is.null(attr(inat_search, "class"))){
    sp_inat_rec_num[sp] <- 200000 #species with close to 200k records cause an error, so set this as the maximum
  }
  save(sp_inat_rec_num, file = "sp_inat_rec_num")

}
}

#convert into a score out of 10, 1 = min, to 2 dp, with 10 being rarest, 1 = 200000+ records

##rescale to 0 to 1
temp_score <- (sp_inat_rec_num - min(sp_inat_rec_num))/(max(sp_inat_rec_num) - min(sp_inat_rec_num))
##reverse
temp_score <- 1 - temp_score
#convert to 1 to 10
inat_sp_scores <- round((9 * temp_score) + 1, 3)

hist(inat_sp_scores)

best_sp <- head(sort(inat_sp_scores, decreasing = T))

#who found these species

best_finds <- subset(RPP_bioblitz_data_RG, scientific_name %in% names(best_sp))[,c("scientific_name", "user_login")]

best_finds$score <- inat_sp_scores[best_finds$scientific_name]
best_finds$records <- sp_inat_rec_num[best_finds$scientific_name]

#sort in descending order
best_finds <- best_finds[order(best_finds$scientific_name, decreasing = T),]

best_finds <- best_finds[order(best_finds$score, decreasing = T),]

datatable(best_finds)

This scoring system isn’t great as most species have very high values, since most species are rarely recorded. But we’ll go with it for now. Ostrea conchaphila is a mis-identification, so Rebecca wins this one as well with her Harmothoe impar record. Well done Rebecca!!

Harmothoe impar