-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathREADME.Rmd
192 lines (146 loc) · 10.9 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
---
output: github_document
editor_options:
chunk_output_type: console
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# zooper <img src='man/figures/logo.png' align="right" height="139" />
<!-- badges: start -->
[![R build status](https://github.com/InteragencyEcologicalProgram/zooper/workflows/R-CMD-check/badge.svg)](https://github.com/InteragencyEcologicalProgram/zooper/actions)
[![Codecov test coverage](https://codecov.io/gh/InteragencyEcologicalProgram/zooper/branch/master/graph/badge.svg)](https://codecov.io/gh/InteragencyEcologicalProgram/zooper?branch=master)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7641064.svg)](https://doi.org/10.5281/zenodo.7641064)
[![Data DOI](https://img.shields.io/badge/Data%20publication%20DOI-10.6073/pasta/8b646dfbeb625e308212a39f1e46f69b-blue.svg)](https://portal.edirepository.org/nis/mapbrowse?scope=edi&identifier=539)
[![Data paper](https://img.shields.io/badge/Data%20paper%20DOI-10.1371/journal.pone.0265402-blue.svg)](https://doi.org/10.1371/journal.pone.0265402)
<!-- badges: end -->
An R package to download and integrate zooplankton data from the Sacramento San Joaquin Delta.
## Installation
You can install the latest version from R-universe with:
``` r
options(repos = c(
sbashevkin = 'https://sbashevkin.r-universe.dev',
CRAN = 'https://cloud.r-project.org'))
install.packages(“zooper”)
```
Or from GitHub with:
``` r
# install.packages("devtools")
devtools::install_github("InteragencyEcologicalProgram/zooper")
```
# Dataset documentation
For a full documentation of this dataset please see the data paper in PLOS ONE or the data publication on EDI
Bashevkin, S. M., R. Hartman, M. Thomas, A. Barros, C. E. Burdi, A. Hennessy, T. Tempel, and K. Kayfetz. 2022. Five decades (1972–2020) of zooplankton monitoring in the upper San Francisco Estuary. PLOS ONE 17: e0265402. [doi:10.1371/journal.pone.0265402](https://doi.org/10.1371/journal.pone.0265402)
Bashevkin, S. M., R. Hartman, M. Thomas, A. Barros, C. Burdi, A. Hennessy, T. Tempel, K. Kayfetz, K. Alstad, and C. Pien. 2023. Interagency Ecological Program: Zooplankton abundance in the Upper San Francisco Estuary from 1972-2021, an integration of 7 long-term monitoring programs. ver 4. Environmental Data Initiative. [doi:10.6073/pasta/8b646dfbeb625e308212a39f1e46f69b](https://portal.edirepository.org/nis/mapbrowse?scope=edi&identifier=539)
# Introduction
This package has 2 main functions and a few accessory functions. The `Zoopdownloader` function downloads the zooplankton datasets from their respective online sources and converts them to a consistent format. The `Zoopsynther` function takes zooplankton data from different surveys and integrates the data according to user-specified parameter choices.
This package is also accessible through a [shiny app](https://deltascience.shinyapps.io/zoopsynth) [(code and installation instructions for latest version available here)](https://github.com/InteragencyEcologicalProgram/ZoopSynth). The app is a GUI (graphical user interface) that allows users without R experience to run the zooplankton synthesizer function and download the resulting data. The shiny app also allows users with all experience levels to easily visualize the data.
## Community or taxon-specific analyses?
The biggest problem with integrating zooplankton datasets is variability in taxonomic resolution. To resolve this, we have developed 2 approaches to consolidating inconsistent data to "least common denominator taxa." Depending on what type of analysis you wish to run, you may wish for different types of synthesized data.
### For community data analyzers
*I want to analyze the community composition at whatever taxonomic level lets me use all these datasets.*
- Consistent taxonomic categories
- No plankters counted more than once
- Sacrifices some taxonomic resolution
- Removes taxa with no relatives in all datasets (e.g., Annelida)
### For specific taxa analyzers
*I want all possible data on these specific taxa.*
- Calculates total CPUE for higher taxonomic levels
- Some plankters appear in multiple nested taxa (e.g., Calanoida, Copepoda)
- Preserves taxonomic resolution and creates taxonomic categories that are comparable across all datasets
- Labels taxa that are comparable across all datasets, warns about those that are not.
## Size classes
We have integrated zooplankton data from 3 net size classes:
1. Macro (500 - 505 μm): Amphipods and mysids (NOTE: Prior to 1974 EMP macrozooplankton were sampled with a 930 μm mesh net)
2. Meso (150 - 160 μm): Copepods, cladocera
3. Micro (43 - 50 μm): Copepods, rotifers
Nets accurately sample zooplankton larger than the mesh size. Zooplankton smaller than the mesh size are still captured and often recorded in datasets, but the resulting CPUEs are not accurate. To account for this we:
1. Resolve taxonomic resolution separately within each net size class.
2. If `Data = 'Taxa'`, we mark "summed groups" with the net size class from which they were derived.
3. All potentially undersampled data are marked with a flag `Undersampled == TRUE`
4. For the plots in the shiny app, all data with `Undersampled == TRUE` can be removed. However, data downloaded from the app do contain undersampled data.
## Changing taxonomic resolution over time
For many studies, taxonomic resolution has changed over time. This could confound analyses of zooplankton communities and abundances over time. To account for this, we have implemented a solution for the `Data_type="Community"` option, which can be implemented by setting `Time_consistency = TRUE`.
We first find all taxa that were not counted every year across the date range the user inputs (but taking into account the years non-native species were introduced and each survey first started sampling). These taxa are then summed to higher taxonomic levels, as is done for taxa that were not counted across all datasets.
Often, non-native species are not added to zooplankton species list the same year they are first detected in the system. To allow for some lag between introduction years and the years these species were first counted, you can change the `Intro_lag` option (currently defaults to 2 years).
## Biomass
Functionality to output biomass (carbon biomass per unit effort in $\mu g$ $m^{-3}$) is now included in zooper. However, biomass conversions are not available for all taxa and life stages. Micro and meso zooplankton are converted to biomass using average biomass values from the literature (see `biomass_mesomicro` for sources). The macrozooplankton are converted to biomass using length-weight equations (see `biomass_macro` for sources). Length data are currently only published online for EMP, so only EMP macro zooplankton biomass is available through zooper, and only for the two mysid taxa with dry weight length-weight equations from formalin preserved specimens (see `biomass_macro` for the full set of equations). As more conversions become available for any size class, they can be added to zooper to increase the biomass coverage.
# Usage
```{r}
library(zooper)
MyZoops <- Zoopsynther(Data_type = "Community",
Response = c("CPUE", "BPUE"),
Sources = c("EMP", "FRP", "FMWT"),
Size_class = "Meso",
Date_range = c("1990-10-01", "2000-09-30"))
str(MyZoops)
```
Here's a graph you could make with the data
```{r plots, message=FALSE, warning=FALSE, dpi=400, fig.height=7}
library(dplyr)
library(ggplot2)
library(RColorBrewer)
set.seed(16)
MyZoops%>%
filter(!is.na(SalSurf))%>%
mutate(Salinity_zone=case_when(
SalSurf < 0.5 ~ "Freshwater",
SalSurf > 0.5 & SalSurf < 6 ~ "Low salinity zone",
SalSurf > 6 ~ "High salinity zone"
))%>%
mutate(Salinity_zone=factor(Salinity_zone, levels=c("Freshwater", "Low salinity zone", "High salinity zone")))%>%
group_by(Year,Phylum, Class, Order, Family, Genus, Species, Lifestage, Taxlifestage, Salinity_zone)%>%
summarise(CPUE=mean(CPUE, na.rm=T), .groups="drop")%>%
arrange(Phylum, Class, Order, Family, Genus, Species, Lifestage)%>%
mutate(Taxlifestage=factor(Taxlifestage, unique(Taxlifestage)))%>%
ggplot(aes(x=Year, y=CPUE))+
geom_bar(stat="identity", color="white", linewidth=0.01, aes(fill=Taxlifestage))+
facet_wrap(~Salinity_zone, nrow=1)+
coord_cartesian(expand=0)+
scale_x_continuous(breaks = function(x) unique(floor(pretty(seq(min(x), max(x)), n=3))), expand=c(0,0))+
scale_fill_manual(values=sample(colorRampPalette(brewer.pal(12, "Set3"))(length(unique(MyZoops$Taxlifestage)))),
name="Taxa and life stage",
guide = guide_legend(ncol=3, title.position = "top", title.hjust = 0.5))+
ylab(bquote(Average~CPUE~"("*Catch*"/"*m^3*")"))+
theme_bw()+
theme(panel.grid=element_blank(), text=element_text(size=14), legend.text = element_text(size=8),
legend.key.size = unit(10, "points"), strip.background=element_blank(), legend.position = "bottom",
legend.background = element_rect(color="black"), axis.text.x=element_text(angle=45, hjust=1))
```
Here's the same graph with biomass (although a few taxa were removed for which biomass conversions were not available)
```{r plots2, message=FALSE, warning=FALSE, dpi=400, fig.height=7}
MyZoops%>%
filter(!is.na(SalSurf))%>%
mutate(Salinity_zone=case_when(
SalSurf < 0.5 ~ "Freshwater",
SalSurf > 0.5 & SalSurf < 6 ~ "Low salinity zone",
SalSurf > 6 ~ "High salinity zone"
))%>%
mutate(Salinity_zone=factor(Salinity_zone, levels=c("Freshwater", "Low salinity zone", "High salinity zone")))%>%
group_by(Year,Phylum, Class, Order, Family, Genus, Species, Lifestage, Taxlifestage, Salinity_zone)%>%
summarise(BPUE=mean(BPUE, na.rm=T), .groups="drop")%>%
arrange(Phylum, Class, Order, Family, Genus, Species, Lifestage)%>%
mutate(Taxlifestage=factor(Taxlifestage, unique(Taxlifestage)))%>%
ggplot(aes(x=Year, y=BPUE))+
geom_bar(stat="identity", color="white", linewidth=0.01, aes(fill=Taxlifestage))+
facet_wrap(~Salinity_zone, nrow=1)+
coord_cartesian(expand=0)+
scale_x_continuous(breaks = function(x) unique(floor(pretty(seq(min(x), max(x)), n=3))), expand=c(0,0))+
scale_fill_manual(values=sample(colorRampPalette(brewer.pal(12, "Set3"))(length(unique(MyZoops$Taxlifestage)))),
name="Taxa and life stage",
guide = guide_legend(ncol=3, title.position = "top", title.hjust = 0.5))+
ylab(bquote(Average~BPUE~"("*mu*g*"/"*m^3*")"))+
theme_bw()+
theme(panel.grid=element_blank(), text=element_text(size=14), legend.text = element_text(size=8),
legend.key.size = unit(10, "points"), strip.background=element_blank(), legend.position = "bottom",
legend.background = element_rect(color="black"), axis.text.x=element_text(angle=45, hjust=1))
```
# Code of conduct
Please note that the 'zooper' project is released with a
[Contributor Code of Conduct](CODE_OF_CONDUCT.md).
By contributing to this project, you agree to abide by its terms.