In 2022, the Three Rivers Park District celebrated a Big Year of Birds! This work uses eBird data to summarize birding activity in the parks during the special year-long event. How many species were found? Who documented the most species? How did the year compare to past years? Scroll down to find out!
###########
# Set up #
###########
# Load libraries and define focal year (2022). Most outputs below are filtered and specific to the focal year.
# load packages
library(sf)
library(here)
library(tidyverse)
library(auk)
library(ggthemes)
library(DT)
# custom functions
`%!in%` = Negate(`%in%`)
# resolve namesake conflicts
<- dplyr::select
select
# set focal year
<- 2022
focal_year
########################
# Load park boundaries #
########################
# Load park boundaries from TRPD spatial database. eBird data will be filtered to only retain records from within these boundaries.
# where to save clean parks sf file
<- file.path(here("Data", "Wildlife", "eBird", "parks_outlines_ManualEdits_30mBufferDissolve.RDS"))
f_parks
if (!file.exists(f_parks)) {
<- st_read(here("Data", "Geospatial", "General", "Park_Bndry_Public_ManualEdits_30mBufferDissolve.shp")) %>%
spatial.boundaries.parks st_transform(crs = 4326)
<- spatial.boundaries.parks
parks saveRDS(parks, f_parks)} else {
<- readRDS(f_parks)
parks
}
st_crs(parks) <- 4326
<- parks %>%
parks select(LabelName) %>%
rename(Park_Name = LabelName)
#mapview::mapview(parks, col.regions = "darkgreen", legend = FALSE)
###################
# Load eBird data #
###################
# Raw data were obtained directly from eBird. An account and simple pre-approval are needed to [download the data](https://science.ebird.org/en/use-ebird-data).
# read in eBird data
<- auk_ebd(file = file.path("S:\\Shared drives\\Blair Lab\\Data_External_General\\eBird\\EBD\\ebd_US-MN_relDec-2022\\ebd_US-MN_relDec-2022.txt"),
ebd file_sampling = file.path("S:\\Shared drives\\Blair Lab\\Data_External_General\\eBird\\EBD\\ebd_sampling_relDec-2022\\ebd_sampling_relDec-2022.txt"))
# define some attributes of starting EDB version and planned filtering to populate output file names
<- "ebd_relDec-2022" # [UPDATE FOR RUN]
ebd_version <- "TRPD_parks_manual_30mBuff" # [UPDATE FOR RUN]
filter_region <- "all_sp" # [UPDATE FOR RUN]
filter_sp <- "all_years" # [UPDATE FOR RUN]
filter_season
# define filters to apply to the EBD
<- ebd %>%
ebd_filters # select only records from study area
auk_bbox(parks) #%>%
# # data from any year but, could also filter
# auk_date(date = c("2018-01-01", "2022-12-31"))
# define where filtered outputs will live
<- file.path(here("Data", "Wildlife", "eBird", paste0(ebd_version,"_",filter_region,"_",filter_sp,"_",filter_season,".txt")))
f_ebd
<- file.path(here("Data", "Wildlife", "eBird", paste0(ebd_version,"_","checklists","_",filter_region,"_",filter_sp,"_",filter_season,".txt")))
f_sampling
# implement filter, but 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)
}
# define where park-point intersection will live (yielding only records within park boundaries)
<- file.path(here("Data", "Wildlife", "eBird", paste0(ebd_version,"_",filter_region,"_",filter_sp,"_",filter_season,"_within_park_boundaries_int.RDS")))
f_int
# define where park-point filter will live (interim step without the park info)
<- file.path(here("Data", "Wildlife", "eBird", paste0(ebd_version,"_",filter_region,"_",filter_sp,"_",filter_season,"_within_park_boundaries_filter.RDS")))
f_filter
# read filtered ebd and and clip to park boundaries, but only run if the files don't already exist
if (!file.exists(f_filter)) {
<- read_ebd(f_ebd, unique = FALSE, rollup = TRUE) %>%
dat st_as_sf(coords = c("longitude", "latitude"), crs = 4326)
<- dat %>%
dat select(global_unique_identifier, common_name, observation_count, locality, locality_id, locality_type, observation_date, time_observations_started, observer_id, sampling_event_identifier, protocol_type, duration_minutes, effort_distance_km, number_observers, all_species_reported, group_identifier)
<- st_filter(dat, parks) %>%
dat_parks mutate(Year = format(as.Date(observation_date, format="%Y-%m-%d"),"%Y")) # add column for year
saveRDS(dat_parks, f_filter)
else {
} <- readRDS(f_filter)
dat_parks
}
# dat_parks_int <- st_intersection(dat_parks, parks)
### st_intersection taking too long. this loop is faster....
if (!file.exists(f_int)) {
# convert polygons to multipart polygons (one per park)
<- parks %>%
parks_mp group_by(Park_Name) %>%
summarise(geometry = st_combine(geometry))
<- data.frame()
dat_parks_int for (i in 1:nrow(parks_mp)) {
<- parks_mp$Park_Name[[i]]
park_name <-parks_mp[i,]
park<- st_filter(dat_parks,park)
park_dat $Park_Name <- park_name
park_dat<- rbind(dat_parks_int, park_dat)
dat_parks_int
}
saveRDS(dat_parks_int, f_int)
else {
} <- readRDS(f_int)
dat_parks_int
}
<- dat_parks_int
dat_parks rm(dat_parks_int)
# save checklist locations with total number as sf for later before dropping geometry
<-dat_parks %>%
checklist_locations select(locality_id, locality_type, locality, Park_Name) %>%
unique()
<-dat_parks %>%
checklist_locations_visit_count select(locality_id, locality_type, locality, sampling_event_identifier, Park_Name) %>%
unique() %>%
group_by(locality_id) %>%
summarise(total_visits = n()) %>%
st_drop_geometry()
<- left_join(checklist_locations, checklist_locations_visit_count)
checklist_locations
# Expand locality type codes
$locality_type[which(checklist_locations$locality_type == "H")] <- "Hotspot"
checklist_locations$locality_type[which(checklist_locations$locality_type == "P")] <- "Personal point"
checklist_locations$locality_type[which(checklist_locations$locality_type == "PC")] <- "Postal code"
checklist_locations
<- dat_parks %>%
dat_parks st_drop_geometry()
###########################
# Generate data summaries #
###########################
# This code summarizes data from the focal year (`r focal_year`) for each observer, park, and species. Visualizations and other displays of these summaries are below.
# Convert count of X to 1
$observation_count[which(dat_parks$observation_count == "X")] <- 1
dat_parks
$observation_count <- as.numeric(dat_parks$observation_count)
dat_parks
# Focal year summary by observer
<- dat_parks %>%
observer_summaries st_drop_geometry() %>%
filter(Year == focal_year) %>%
group_by(observer_id) %>%
summarize(total_species = length(unique(common_name)),
total_birds = sum(as.numeric(observation_count)), # count of individual birds
total_parks_visited = length(unique(Park_Name)),
total_visits = length(unique(paste0(Park_Name,"_",observation_date))),
total_checklists = length(unique(sampling_event_identifier))) %>%
arrange(desc(total_species)) %>%
ungroup()
<- dat_parks %>%
observer_summaries_effort filter(Year == focal_year) %>%
select(observer_id, sampling_event_identifier, Year, duration_minutes, effort_distance_km) %>%
unique() %>%
group_by(observer_id) %>%
summarize(total_hours_birded = round(sum(duration_minutes, na.rm = TRUE)/60,1),
total_miles_birded = round(sum(effort_distance_km, na.rm = TRUE)*0.621371,1))
<- left_join(observer_summaries, observer_summaries_effort)
observer_summaries
# top observers, focal year
<- slice_head(observer_summaries, n = 10) %>%
top_observers pull(observer_id)
## Get observer names from eBird webiste
library(rvest)
<- function(sampling_event){
get_name_from_checklist read_html(paste0("https://ebird.org/checklist/",sampling_event)) %>%
html_elements("meta") %>%
html_attr("content") %>%
10]
.[
}
<- Vectorize(get_name_from_checklist)
get_name_from_checklist
library(ratelimitr)
<- limit_rate(get_name_from_checklist, rate(n = 1, period = 6))
get_name_from_checklist_lim
<- here("Data", "Wildlife", "eBird", paste0("top_observer_names_",focal_year,".RDS"))
f_obs_names
<- dat_parks %>%
observer_names filter(Year == focal_year) %>%
select(observer_id, sampling_event_identifier) %>%
group_by(observer_id) %>%
filter(sampling_event_identifier == first(sampling_event_identifier)) %>%
slice(1) %>%
filter(observer_id %in% top_observers)
if (file.exists(f_obs_names)) {
<- readRDS(f_obs_names)
observer_names_existing <- left_join(observer_names, observer_names_existing, by = c("observer_id"))}
observer_names
if (!file.exists(f_obs_names)) {
<- observer_names %>%
observer_names mutate(observer_name = NA)
<- data.frame(matrix(nrow=0, ncol=3))
observer_names_existing colnames(observer_names_existing) <- colnames(observer_names)
<- observer_names_existing %>%
observer_names_existing mutate(observer_id = as.character(observer_id),
observer_name = as.character(observer_name))
}
<- filter(observer_names, is.na(observer_name)) %>%
observer_names_needed mutate(observer_name = get_name_from_checklist_lim(sampling_event_identifier)) %>%
select(observer_id, observer_name)
if (nrow(observer_names_needed) != 0) {
<- bind_rows(observer_names_existing, observer_names_needed) %>%
observer_names select(observer_id, observer_name)} else {
<- observer_names_existing
observer_names
}
saveRDS(observer_names, f_obs_names)
<- observer_summaries %>%
observer_summaries left_join(observer_names) %>%
relocate(observer_name) %>%
mutate(observer_name = ifelse(observer_name == "Anonymous eBirder", observer_id, observer_name), # replace anonymous people with their ID
observer = ifelse(!is.na(observer_name), observer_name, observer_id))
$observer <- reorder(observer_summaries$observer, -observer_summaries$total_species)
observer_summaries
# Focal year summary by park
<- dat_parks %>%
park_summaries filter(Year == focal_year) %>%
group_by(Park_Name) %>%
summarize(total_species = length(unique(common_name)),
total_birds = sum(as.numeric(observation_count)), # count of individual birds
total_visitors = length(unique(observer_id)),
total_visits = length(unique(paste0(observer_id,"_",observation_date))),
total_checklists = length(unique(sampling_event_identifier))) %>%
arrange(desc(total_species))
<- dat_parks %>%
park_summaries_effort filter(Year == focal_year) %>%
select(observer_id, sampling_event_identifier, Year, duration_minutes, effort_distance_km, Park_Name) %>%
unique() %>%
group_by(Park_Name) %>%
summarize(total_hours_birded = round(sum(duration_minutes, na.rm = TRUE)/60,1),
total_miles_birded = round(sum(effort_distance_km, na.rm = TRUE)*0.621371,1))
<- left_join(park_summaries, park_summaries_effort)
park_summaries
# Focal year summary by species (max count by park)
<- dat_parks %>%
species_list filter(Year == focal_year) %>%
pivot_wider(id_cols = common_name, names_from = Park_Name, values_from = observation_count, values_fn = max) %>%
left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(common_name = "comName")) %>%
arrange(taxonOrder) %>%
select(-taxonOrder)
# Focal year summary by species (summary)
<- dat_parks %>%
species_summary filter(Year == focal_year) %>%
group_by(common_name) %>%
summarize(total_counted = sum(as.numeric(observation_count)),
high_count = as.numeric(max(observation_count)),
total_parks = length(unique(Park_Name)),
total_observers = length(unique(observer_id)),
total_days_observed = length(unique(observation_date))) %>%
left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(common_name = "comName")) %>%
arrange(taxonOrder) %>%
select(-taxonOrder)
# Summaries by year across all parks & observers
<- dat_parks %>%
year_summaries group_by(Year) %>%
summarize(total_species = length(unique(common_name)),
total_birds = sum(as.numeric(observation_count)), # count of individual birds
total_visitors = length(unique(observer_id)),
total_visits = length(unique(paste0(observer_id,"_",Park_Name,"_",observation_date))),
total_checklists = length(unique(sampling_event_identifier)))
<- dat_parks %>%
year_summaries_effort select(observer_id, sampling_event_identifier, Year, duration_minutes, effort_distance_km, Park_Name) %>%
unique() %>%
group_by(Year) %>%
summarize(total_hours_birded = round(sum(duration_minutes, na.rm = TRUE)/60,1),
total_miles_birded = round(sum(effort_distance_km, na.rm = TRUE)*0.621371,1))
<- left_join(year_summaries, year_summaries_effort) %>%
year_summaries arrange(desc(Year))
# Species list for "winning" observer
<- observer_summaries$observer_id[which(observer_summaries$total_species == max(observer_summaries$total_species))]
winning_observer
<- winning_observer
focal_observer <- dat_parks %>%
observer_species_list filter(observer_id == winning_observer) %>%
filter(Year == focal_year) %>%
pivot_wider(id_cols = common_name, names_from = Park_Name, values_from = observation_count, values_fn = max) %>%
left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(common_name = "comName")) %>%
arrange(taxonOrder) %>%
select(-taxonOrder)
#observer_species_list[is.na(observer_species_list)] <- ""
<- dat_parks %>% filter(Year == focal_year)
dat_parks_focal_year
# biggest day
<- dat_parks_focal_year %>%
biggest_days group_by(observer_id, observation_date) %>%
summarize(n_sp = length(unique(common_name)),
length(unique(Park_Name))) %>%
arrange(desc(n_sp))
# largest counts ever
<- dat_parks %>%
high_counts slice_max(observation_count, n = 20)
# new high counts
<- dat_parks %>%
new_high_counts group_by(common_name, Year) %>%
summarize(high_count = max(observation_count)) %>%
filter(high_count == max(high_count)) %>%
filter(Year == min(Year)) %>%
filter(Year == focal_year) %>%
left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(common_name = "comName")) %>%
arrange(taxonOrder) %>%
select(-taxonOrder)
# SGCN
# determine SGCN sp in system
<- read_csv(here("Data", "Wildlife", "sgcn_2015-25_list_excel.csv")) %>%
SGCN filter(Taxa == "Birds")
$SGCN <- 1 # make new column indicating species is on list
SGCN# align with eBird common names
$ComName[which(SGCN$ComName == "Le Conte's Sparrow")] <- "LeConte's Sparrow"
SGCN$ComName[which(SGCN$ComName == "Nelson's Sparrow")] <- "Nelson's Sparrow"
SGCN$ComName[which(SGCN$ComName == "Rufa Red Knot")] <- "Red Knot"
SGCN$ComName[which(SGCN$ComName == "Belted kingfisher")] <- "Belted Kingfisher"
SGCN$ComName[which(SGCN$ComName == "Black-crowned Night-heron")] <- "Black-crowned Night-Heron"
SGCN$ComName[which(SGCN$ComName == "Greater Prairie-chicken")] <- "Greater Prairie-Chicken"
SGCN<- SGCN %>%
SGCN left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(ComName = "comName")) %>%
rename(common_name = "ComName")
<- dat_parks_focal_year %>%
SGCN_records filter(common_name %in% unique(SGCN$common_name)) %>%
group_by(common_name) %>%
summarize(total_counted = sum(as.numeric(observation_count)),
high_count = as.numeric(max(observation_count)),
total_parks = length(unique(Park_Name)),
total_observers = length(unique(observer_id)),
total_days_observed = length(unique(observation_date))) %>%
left_join(SGCN)
# how many new birders in focal year?
<- dat_parks %>%
obs_focal_year filter(Year == focal_year)
<- unique(obs_focal_year$observer_id)
obs_focal_year
<- dat_parks %>%
obs_pre_focal_year filter(Year != focal_year)
<- unique(obs_pre_focal_year$observer_id)
obs_pre_focal_year
<- setdiff(obs_focal_year, obs_pre_focal_year) obs_new_focal_year
eBirding activity in the parks has grown dramatically since eBird was launched in 2002. Some metrics peaked in 2020, likely due to changes in birding activity and outdoor recreation related to COVID-19 restrictions. Data from before 2002 have been entered by eBirders retroactively.
%>%
year_summaries pivot_longer(cols = c( -Year), names_to = "variable") %>%
mutate(Year = as.numeric(Year)) %>%
filter(variable %!in% c("total_birds", "total_checklists")) %>%
mutate(variable = recode(variable, "total_visits" = "Total visits", "total_visitors" = "Total eBirders", "total_species" = "Number of species documented", "total_miles_birded" = "Total miles birded", "total_hours_birded" = "Total hours birded"),
variable = factor(variable, levels=c("Total eBirders", "Total visits", "Total miles birded", "Total hours birded", "Number of species documented"))) %>%
ggplot(aes(x = Year)) +
geom_line(aes(y = value, color = variable), alpha = .9) +
geom_point(aes(y = value, color = variable), alpha = .9) +
scale_x_continuous(breaks = seq(1960, 2022, by = 10)) +
theme_clean() +
labs(
#title = "eBirding in Three Rivers Parks",
#x = "Year",
y = "") +
theme(
plot.title = element_text(size = 11, face = "bold"),
plot.subtitle = element_text(size = 10, face = "italic"),
legend.position = "none",
plot.background=element_blank()) +
facet_wrap(~variable, ncol = 2, scales = "free")
This chart summarizes the total number of visits by eBirders to Three Rivers Parks on each day of the year. There is a strong seasonal component to this metric, with birders most active during the spring. Some days with special events that generally increased birding activity in the parks are called out with labels.
<- data.frame(observation_date = c("2022-05-14",
special_dates "2022-10-08",
"2022-09-10",
"2022-06-11",
"2022-12-17"),
label = c("eBird Global Big Day",
"eBird October Big Day",
"Three Rivers Big Day",
"Three Rivers Big Sit",
"West Hennepin CBC")) %>%
mutate(observation_date = as.Date(observation_date, format="%Y-%m-%d"),
Date = lubridate::yday(observation_date),
Year = format(observation_date,"%Y"))
<- dat_parks %>%
visits_doy_dat #filter(Year == focal_year) %>%
select(Year, observer_id, Park_Name, observation_date) %>%
unique() %>%
mutate(Date = lubridate::yday(observation_date)) %>%
group_by(Year, Date) %>%
summarize(Visit_count = n()) %>%
ungroup() %>%
left_join(select(special_dates, -observation_date))
#visits_doy_dat$label[which(is.na(visits_doy_dat$label))] <- ""
library(ggtext)
<- ggplot() +
visits_plot # last 15 years background
geom_line(mapping = aes(x = as.Date(Date, origin = as.Date("2022-01-01")), y = Visit_count, group = Year), data = filter(visits_doy_dat, Year >= 2010), color = "grey", linewidth = .5, alpha = .85) +
# focal year highlight
geom_line(mapping = aes(x = as.Date(Date, origin = as.Date("2022-01-01")), y = Visit_count, group = Year), data = filter(visits_doy_dat, Year == focal_year), color = "#1a5b73", linewidth = 1) +
# label special dates
::geom_label_repel(mapping = aes(label = label, x = as.Date(Date, origin = as.Date("2022-01-01")), y = Visit_count, group = Year), data = filter(visits_doy_dat, Year == focal_year), color = "#1a5b73", size = 2, box.padding = 1, segment.color = "grey20", seed = 3, ylim = c(50, 68)) +
ggrepel
theme_clean() +
labs(
title = "<span style='font-size:10pt'>Visits to Three Rivers parks by eBirders in
<span style='color:#1a5b73;'>2022</span> and other years
<span style='color:grey60;'>since 2010</span>
</span>",
x = "Date",
y = "Visits") +
theme(
plot.title = element_markdown(lineheight = 1.1, face ="bold"),
plot.subtitle = element_text(size = 10, face = "italic"),
legend.title = element_text(size = 10, face = "plain"),
plot.background=element_blank(),
axis.title.x = element_blank()) +
scale_x_date(date_labels = "%b", date_breaks = "1 month", expand = c(.01,00))
visits_plot
This map shows checklist starting locations. The size of each point scaled to the number of checklists submitted from that location. Large points with many visits are typically official eBird hotspots. Please note that this analysis includes a 30 m buffer around the official boundaries of the parks to capture checklists that were started immediately adjacent to parks (e.g., observers that started their checklist just outside of the park before travelling into the park).
library(mapview)
mapview(checklist_locations, zcol = "locality_type", col.regions = c("red", "purple", "grey"), cex = "total_visits",
popup = c("locality", "locality_type", "total_visits", "Park_Name"),
label = "locality") +
mapview(parks, col.regions = "palegreen4", legend = FALSE)
The most frequently visited park by eBirders in 2022 was Carver Park Reserve. The park visited by the greatest number of different individual eBirders was Hyland Lake Park Reserve. The park with the greatest observed bird diversity was Carver Park Reserve, with 207 species documented over the course of the year.
library(DT)
%>%
park_summaries relocate(Park_Name) %>%
datatable(options = list(pageLength = 33),
colnames = c("Park", "Species counted", "Birds counted", "Total eBirders", "Total visits", "Checklists submitted", "Hours birded", "Miles birded"),
caption = "2022 TRPD Big Year of Birds: results by park") %>%
formatCurrency(purrr::map_lgl(.$x$data, is.numeric), currency = "", interval = 3, digits = 0, mark = ",") %>%
formatCurrency(c("total_hours_birded", "total_miles_birded"), currency = "", interval = 3, digits = 1, mark = ",") %>%
formatStyle(
'total_species',
background = styleColorBar(park_summaries$total_species, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_birds',
background = styleColorBar(park_summaries$total_birds, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_visitors',
background = styleColorBar(park_summaries$total_visitors, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_visits',
background = styleColorBar(park_summaries$total_visits, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_checklists',
background = styleColorBar(park_summaries$total_checklists, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_hours_birded',
background = styleColorBar(park_summaries$total_hours_birded, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_miles_birded',
background = styleColorBar(park_summaries$total_miles_birded, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center')
A total of 747 different individuals submitted checklists in Three Rivers parks in 2022.
%>%
observer_summaries relocate(observer) %>%
select(-c(observer_id, observer_name)) %>%
datatable(options = list(pageLength = 25),
colnames = c("Observer", "Species counted", "Birds counted", "Parks visited", "Total visits", "Checklists submitted", "Hours birded", "Miles birded"),
caption = "2022 TRPD Big Year of Birds: results by observer") %>%
formatCurrency(purrr::map_lgl(.$x$data, is.numeric), currency = "", interval = 3, digits = 0, mark = ",") %>%
formatCurrency(c("total_hours_birded", "total_miles_birded"), currency = "", interval = 3, digits = 1, mark = ",") %>%
formatStyle(
'total_species',
background = styleColorBar(observer_summaries$total_species, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_birds',
background = styleColorBar(observer_summaries$total_birds, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_parks_visited',
background = styleColorBar(observer_summaries$total_parks_visited, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_visits',
background = styleColorBar(observer_summaries$total_visits, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_checklists',
background = styleColorBar(observer_summaries$total_checklists, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_hours_birded',
background = styleColorBar(observer_summaries$total_hours_birded, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_miles_birded',
background = styleColorBar(observer_summaries$total_miles_birded, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center')
The table below provides information on all 240 bird species documented in the parks in 2022. The list is sorted taxonomically, but it can also be sorted by other metrics. The “Total counted” column sums the total number of individual birds counted over the course of the year. Note that same individual bird can be counted multiple times by different observers on different days. The High count column records the highest count of a species recorded on a single checklist.
%>%
species_summary datatable(options = list(pageLength = 120),
colnames = c("Species", "Total counted", "High count", "Total parks observed in", "Total observers", "Total days observed"),
caption = "2022 TRPD Big Year of Birds: results by species") %>%
formatCurrency(purrr::map_lgl(.$x$data, is.numeric), currency = "", interval = 3, digits = 0, mark = ",") %>%
formatStyle(
'total_counted',
background = styleColorBar(species_summary$total_counted, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'high_count',
background = styleColorBar(species_summary$high_count, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_parks',
background = styleColorBar(species_summary$total_parks, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_observers',
background = styleColorBar(species_summary$total_observers, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_days_observed',
background = styleColorBar(species_summary$total_days_observed, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center')
This table summarizes eBirding effort and outcomes in the parks from year to year.
library(DT)
%>%
year_summaries relocate(Year) %>%
datatable(options = list(pageLength = 25),
colnames = c("Year", "Species counted", "Birds counted", "Total eBirders", "Total visits", "Checklists submitted", "Hours birded", "Miles birded"),
caption = "TRPD eBirding summary by year (across all parks)") %>%
formatCurrency(purrr::map_lgl(.$x$data, is.numeric), currency = "", interval = 3, digits = 0, mark = ",") %>%
formatStyle(
'total_species',
background = styleColorBar(year_summaries$total_species, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_birds',
background = styleColorBar(year_summaries$total_birds, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_visitors',
background = styleColorBar(year_summaries$total_visitors, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_visits',
background = styleColorBar(year_summaries$total_visits, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_checklists',
background = styleColorBar(year_summaries$total_checklists, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_hours_birded',
background = styleColorBar(year_summaries$total_hours_birded, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center') %>%
formatStyle(
'total_miles_birded',
background = styleColorBar(year_summaries$total_miles_birded, '#e6e6e6'),
backgroundSize = '90% 50%',
backgroundRepeat = 'no-repeat',
backgroundPosition = 'center')
Which species were first recorded on eBird in Three Rivers parks in 2022?
<- dat_parks %>%
sp_focal_year filter(Year == focal_year) %>%
left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(common_name = "comName")) %>%
arrange(taxonOrder) %>%
select(-taxonOrder) %>%
pull(common_name) %>%
unique()
<- dat_parks %>%
sp_prior_years filter(Year < focal_year) %>%
left_join(rebird:::tax %>% select(comName, taxonOrder), by = c(common_name = "comName")) %>%
arrange(taxonOrder) %>%
select(-taxonOrder) %>%
pull(common_name) %>%
unique()
<- setdiff(sp_focal_year, sp_prior_years)
sp_new <- setdiff(sp_prior_years, sp_focal_year)
sp_missing
<- length(unique(dat_parks$Year))
total_years
<- dat_parks %>%
sp_new_info filter(common_name %in% sp_new) %>%
group_by(common_name) %>%
summarize(first_observed = min(observation_date),
total_days_observed = length(unique(observation_date)),
total_observers = length(unique(observer_id)),
parks_observed_in = paste(unique(Park_Name), collapse = ', '))
datatable(sp_new_info,
colnames = c("Species", "Date first observed", "Total days observed", "Number of observers", "Parks observed in"),
caption = paste0("Species observed in Three Rivers parks for the first time in ", focal_year, "."))
Which species have been recorded in the past that weren’t seen in 2022?
<- dat_parks %>%
sp_missing_info filter(common_name %in% sp_missing) %>%
group_by(common_name) %>%
summarize(last_observed = max(observation_date),
years_previously_observed = length(unique(Year)),
#pct_years_observed = round(length(unique(Year))/total_years*100),
total_days_previously_observed = length(unique(observation_date)),
high_count = max(observation_count),
parks_previously_observed_in = paste(unique(Park_Name), collapse = ', '))
datatable(sp_missing_info, options = list(pageLength = 25),
colnames = c("Species", "Date last observed", "Number years previously observed", "Number days previously observed", "High count", "Parks observed in"),
caption = paste0("Species not observed in Three Rivers parks in ", focal_year, " that have been documented in previous years."))
This table provides the highest count of each species submitted in each park in 2022. It is helpful for identifying in which parks individual species have been documented, as well as a general sense of their relative abundance at each. We recommend searching this large table for particular species of interest.
datatable(
rownames = FALSE, colnames = c("Species" = "common_name"),
species_list, caption = paste0("High counts of each species in each park in ", focal_year, "."),
extensions = 'FixedColumns',
options = list(
pageLength = 6,
#dom = 't',
scrollX = TRUE,
fixedColumns = TRUE
) )
This table lists species for which a new district-wide high count was set in 2022.
datatable(
select(new_high_counts, -Year), rownames = FALSE, colnames = c("Species" = "common_name", "New high count" = "high_count"),
caption = paste0("New species high counts recorded in ", focal_year, "."),
extensions = 'FixedColumns',
options = list(
pageLength = 40,
#dom = 't',
scrollX = TRUE,
fixedColumns = TRUE
) )
A selection of bird photographs from 2022 taken within Three Rivers parks.
sessionInfo()
By Sam Safran