diff --git a/DESCRIPTION b/DESCRIPTION index 01f54531..cbac8c74 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA -Version: 0.10.0 -Date: 2025-5-6 +Version: 0.10.1 +Date: 2026-1-7 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( @@ -45,7 +45,7 @@ Suggests: tidyr, covr Encoding: UTF-8 -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 Config/testthat/edition: 3 Config/Needs/website: r-lib/pkgdown, diff --git a/NEWS.md b/NEWS.md index 446706ae..a4187fb6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,15 @@ +# FSA 0.10.1 +* Updated the PSD and Relative Weight computation articles to reflect the changes to `psdVal()`, `psdAdd()`, `wsVal()`, and `wrAdd()`. +* `chapmanRobson()`: Added catch for when n+T<1 and n+T<2. This addresses [#131](https://github.com/fishR-Core-Team/FSA/issues/131)). +* `metaM()`: Added `method="HamelCope"` to address [#133](https://github.com/fishR-Core-Team/FSA/issues/133). A few minor edits to documentation. +* `psdAdd()`: Addressed bugs as described in [#136](https://github.com/fishR-Core-Team/FSA/issues/136)) and [#137](https://github.com/fishR-Core-Team/FSA/issues/137). Added `thesaurus` functionality. Reworked examples in documentation. Reworked testing framework. Thanks to Dave Glover. +* `PSDlit`: Added info for Flier and Longear Sunfish to address [#122](https://github.com/fishR-Core-Team/FSA/issues/122)) and Northern Pikeminnow. Also updated information for Alabama Bass and Spotted Bass. Duplicated lines that combine `species` and `group` to partially address [#137](https://github.com/fishR-Core-Team/FSA/issues/137). +* `psdVal()`: Added `dat=` to allow more flexibility when called from `psdAdd()`. +* `PSDWRTest`: Added for testing PSD and relative weight functions. +* `wrAdd()`: Addressed bugs similar to those for `psdAdd()`. Added `thesaurus` functionality. Reworked examples in documentation. Reworked testing framework (especially expanded validation of results with hand-calculations). +* `wSlit`: Added info for Flier and Longear Sunfish to address [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). Also updated information for Alabama Bass (further removed Spotted Bass (Alabama subspecies)), Spotted Bass, and Northern Pikeminnow (further removed Northern Squawfish (synonym of Northern Pikeminnow that is no longer used)). Duplicated lines that combine `species` and `group` to partially address [#137](https://github.com/fishR-Core-Team/FSA/issues/137). +* `wsVal()`: Added `dat=` to allow more flexibility when called from `wrAdd()`. + # FSA 0.10.0 * Updated `test-coverage.yaml` and moved a `# nocov start` and `# nocov end` in `bootstrap.r` to address the errors with `test-coverage.yaml`. Addresses [#118](https://github.com/fishR-Core-Team/FSA/issues/118). * Removed `DescTools`, `plyr`, `psych` from Suggests (and all their uses in tests and linked code in documentation). Removed `ggplot2`, `marked`, `rcapture`, and `tibble` from Suggests (and use in examples was put in a `\dontrun()`). @@ -122,11 +134,11 @@ * `fitPlot()`: **REMOVED** (to `FSAmisc`). * `fsaNews()` and `FSANews()`: **Removed**. * `psdAdd()`: Modified. Changed the way `PSDlit` was loaded into the function environment so that `FSA::psdAdd()` will work. Addresses [#85](https://github.com/fishR-Core-Team/FSA/issues/85). -* `PSDLit`: Modified. Added info for Utah Chub (from [here](https://webpages.uidaho.edu/quistlab/publications/NAJFM_2021_Black_et_al_UTC_Ws_length_categories.pdf); address [#84](https://github.com/fishR-Core-Team/FSA/issues/84)). +* `PSDLit`: Modified. Added info for Utah Chub (from [here](https://www.usgs.gov/publications/proposed-standard-weight-ws-equation-and-length-categories-utah-chub); address [#84](https://github.com/fishR-Core-Team/FSA/issues/84)). * `psdVal()`: Modified. Changed the way `PSDlit` was loaded into the function environment so that `FSA::psdVal()` will work. Addresses [#85](https://github.com/fishR-Core-Team/FSA/issues/85). * `residPlot()`: **REMOVED** (to `FSAmisc`). * `wrAdd()`: Modified. Changed the way `WSlit` was loaded into the function environment so that `FSA::wrAdd()` will work. Addresses [#85](https://github.com/fishR-Core-Team/FSA/issues/85). -* `WSLit`: Modified. Added info for Utah Chub (from [here](https://webpages.uidaho.edu/quistlab/publications/NAJFM_2021_Black_et_al_UTC_Ws_length_categories.pdf); address [#84](https://github.com/fishR-Core-Team/FSA/issues/84)). +* `WSLit`: Modified. Added info for Utah Chub (from [here](https://www.usgs.gov/publications/proposed-standard-weight-ws-equation-and-length-categories-utah-chub); address [#84](https://github.com/fishR-Core-Team/FSA/issues/84)). * `wsVal()`: Modified. Changed the way `WSlit` was loaded into the function environment so that `FSA::wsVal()` will work. Addresses [#85](https://github.com/fishR-Core-Team/FSA/issues/85). # FSA 0.9.1 diff --git a/R/PSDWRtest.R b/R/PSDWRtest.R new file mode 100644 index 00000000..fc2b00c0 --- /dev/null +++ b/R/PSDWRtest.R @@ -0,0 +1,44 @@ +#' @title Hypothetical weight-length data for testing PSD and relative weight functions +#' +#' @description Hypothetical weight-length and associated data. These data are useful for testing PSD and relative weight functions (e.g., \code{\link{psdAdd}} and \code{\link{wrAdd}}). +#' +#' @name PSDWRtest +#' +#' @docType data +#' +#' @format A data frame of many observations on the following 5 variables: +#' \describe{ +#' \item{species}{Species name} +#' \item{location}{Broad location of capture} +#' \item{len}{Length in mm} +#' \item{wt}{Weight in g} +#' \item{sex}{Sex as \code{F} for female, \code{M} for male, or \code{U} or \code{NA} for unknown or unrecorded} +#' } +#' +#' @section Topic(s): +#' \itemize{ +#' \item Size structure +#' \item Proportional size structure +#' \item Relative stock density +#' \item Proportional stock density +#' \item Relative weight +#' \item Standard weight +#' \item Condition +#' } +#' +#' @concept Size Structure +#' @concept PSD +#' @concept Condition +#' @concept Relative Weight +#' @concept Standard Weight +#' +#' @seealso \code{\link{psdAdd}}, \code{\link{psdCalc}}, and \code{\link{wrAdd}} +#' +#' @keywords datasets +#' +#' @examples +#' str(PSDWRtest) +#' peek(PSDWRtest,n=20) +#' unique(PSDWRtest$species) +#' +NULL diff --git a/R/PSDlit.R b/R/PSDlit.R index 6871db94..f6393258 100644 --- a/R/PSDlit.R +++ b/R/PSDlit.R @@ -1,6 +1,9 @@ #' @title Gabelhouse five-cell length categories for various species. #' #' @description Cutoffs for the Gabelhouse five-cell length categories for a variety of species. +#' +#' @details Entries for some species (e.g., \dQuote{Muskellunge} and \dQuote{Walleye}) have been duplicated for sub-groups to facilitate use with relative weight calculations. For example, entries for \dQuote{Muskellunge (overall)}, \dQuote{Muskellunge (female)}, and \dQuote{Muskellunge (male)} are duplicates of the entry for \dQuote{Muskellunge}; i.e., these entries in \code{PSDlit} are not necessarily just for those sub-groups but this allows for seamless similar computations of relative weights for these sub-groups. +#' #' #' @name PSDlit #' diff --git a/R/WSlit.R b/R/WSlit.R index d6e34ec6..e1d8e4ca 100644 --- a/R/WSlit.R +++ b/R/WSlit.R @@ -3,6 +3,8 @@ #' @description Parameters for all known standard weight equations. #' #' @details The minimum TL for the English units were derived by rounding the converted minimum TL for the metric units to what seemed like common units (inches, half inches, or quarter inches). +#' +#' Entries for \dQuote{Chinook Salmon (landlocked)} and \dQuote{Striped Bass (landlocked)} are the same as for \dQuote{Chinook Salmon} and \dQuote{Striped Bass} but were added to facilitate use with PSD calculations as Gabelhouse lengths are only published for the landlocked sub-group; i.e., these entries in \code{WSlit} are not necessarily just for landlocked populations. #' #' @name WSlit #' diff --git a/R/chapmanRobson.R b/R/chapmanRobson.R index bf8c369c..5cce7685 100644 --- a/R/chapmanRobson.R +++ b/R/chapmanRobson.R @@ -164,7 +164,17 @@ chapmanRobson.default <- function(x,catch,ages2use=age, n <- sum(catch.e,na.rm=TRUE) T <- sum(age.r*catch.e,na.rm=TRUE) ## Estimate S and SE (eqns 6.4 & 6.5 from Miranda & Bettoli (2007)) + if (n+T<1) STOP("The sum of 'catch' (n) and the product of 'age' and 'catch'", + " (T) for 'ages2use' is less than 1, so survival (S) cannot", + " be computed. This usually occurs when 'catch' is actually", + " 'CPE' and the 'CPE' values are very small. If this is the", + " case, consider rescaling your 'CPE' values.") S.est <- T/(n+T-1) + if (n+T<2) STOP("The sum of 'catch' (n) and the product of 'age' and 'catch'", + " (T) for 'ages2use' is less than 2, so the SE of survival (S)", + " cannot be computed. This usually occurs when 'catch' is", + " actually 'CPE' and the 'CPE' values are very small. If this", + " is the case, consider rescaling your 'CPE' values.") S.SE <- sqrt(S.est*(S.est-((T-1)/(n+T-2)))) ## Estimate Z and SE switch(zmethod, diff --git a/R/metaM.R b/R/metaM.R index 865f09dc..b8a68564 100644 --- a/R/metaM.R +++ b/R/metaM.R @@ -13,6 +13,7 @@ #' \item \code{method="HoenigLM"}: The \dQuote{modified Hoenig equation derived with a linear model} as described in Then \emph{et al.} (2015) on the second line of Table 3. Requires only \code{tmax}. #' \item \code{method="HewittHoenig"}: The \dQuote{Hewitt and Hoenig (2005) equation} from their equation 8. Requires only \code{tmax}. #' \item \code{method="tmax1"}: The \dQuote{one-parameter tmax equation} from the first line of Table 3 in Then \emph{et al.} (2015). Requires only \code{tmax}. +#' \item \code{method="HamelCope"}: The equation 7 from Hamel and Cope (2022). Requires only \code{tmax}. #' \item \code{method="K1"}: The \dQuote{one-parameter K equation} from the fourth line of Table 3 in Then \emph{et al.} (2015). Requires only \code{K}. #' \item \code{method="K2"}: The \dQuote{two-parameter K equation} from the fifth line of Table 3 in Then \emph{et al.} (2015). Requires only \code{K}. #' \item \code{method="JensenK1"}: The \dQuote{Jensen (1996) one-parameter K equation}. Requires only \code{K}. @@ -54,15 +55,15 @@ #' \item \code{givens}: A string that contains the input values required by the method to estimate M. #' } #' -#' @section Testing: Kenchington (2014) provided life history parameters for several stocks and used many models to estimate M. I checked the calculations for the \code{PaulyL}, \code{PaulyW}, \code{HoenigO}, \code{HoenigOF}, \code{HoenigO2}, \code{HoenigO2F}, \code{"JensenK1"}, \code{"Gislason"}, \code{"AlversonCarney"}, \code{"Charnov"}, \code{"ZhangMegrey"}, \code{"RikhterEfanov1"}, and \code{"RikhterEfanov2"} methods for three stocks. All results perfectly matched Kenchington's results for Chesapeake Bay Anchovy and Rio Formosa Seahorse. For the Norwegian Fjord Lanternfish, all results perfectly matched Kenchington's results except for \code{HoenigOF} and \code{HoenigO2F}. +#' @section Testing: Kenchington (2014) provided life history parameters for several stocks and used many models to estimate M. I checked the calculations for the \code{"PaulyL"}, \code{"PaulyW"}, \code{"HoenigO"}, \code{"HoenigOF"}, \code{"HoenigO2"}, \code{"HoenigO2F"}, \code{"JensenK1"}, \code{"Gislason"}, \code{"AlversonCarney"}, \code{"Charnov"}, \code{"ZhangMegrey"}, \code{"RikhterEfanov1"}, and \code{"RikhterEfanov2"} methods for three stocks. All results perfectly matched Kenchington's results for Chesapeake Bay Anchovy and Rio Formosa Seahorse. For the Norwegian Fjord Lanternfish, all results perfectly matched Kenchington's results except for \code{"HoenigOF"} and \code{"HoenigO2F"}. #' -#' Results for the Rio Formosa Seahorse data were also tested against results from \code{\link[fishmethods]{M.empirical}} from \pkg{fishmethods} for the \code{PaulyL}, \code{PaulyW}, \code{HoenigO}, \code{HoenigOF}, \code{"Gislason"}, and \code{"AlversonCarney"} methods (the only methods in common between the two packages). All results matched perfectly. +#' Results for the Rio Formosa Seahorse data were also tested against results from \code{\link[fishmethods]{M.empirical}} from \pkg{fishmethods} for the \code{"PaulyL"}, \code{"PaulyW"}, \code{"HoenigO"}, \code{"HoenigOF"}, \code{"Gislason"}, and \code{"AlversonCarney"} methods (the only methods in common between the two packages). All results matched perfectly. #' #' @author Derek H. Ogle, \email{DerekOgle51@gmail.com} #' #' @section IFAR Chapter: 11-Mortality. #' -#' @seealso See \code{\link[fishmethods]{M.empirical}} in \pkg{fishmethods} for similar functionality. +#' @seealso See \code{\link[fishmethods]{M.empirical}} in \pkg{fishmethods} for similar functionality and the "Natural Mortality Tool" Shiny app on-line. #' #' @references Ogle, D.H. 2016. \href{https://fishr-core-team.github.io/fishR/pages/books.html#introductory-fisheries-analyses-with-r}{Introductory Fisheries Analyses with R}. Chapman & Hall/CRC, Boca Raton, FL. #' @@ -74,6 +75,8 @@ #' #' Gislason, H., N. Daan, J.C. Rice, and J.G. Pope. 2010. Size, growth, temperature and the natural mortality of marine fish. Fish and Fisheries 11:149-158. #' +#' Hamel, O. and J. M. Cope. 2022. Development and considerations for application of a longevity-based prior for the natural mortality rate. Fisheries Research 256:106477 [Was (is? from https://www.researchgate.net/publication/363595336_Development_and_considerations_for_application_of_a_longevity-based_prior_for_the_natural_mortality_rate).] +#' #' Hewitt, D.A. and J.M. Hoenig. 2005. Comparison of two approaches for estimating natural mortality based on longevity. Fishery Bulletin. 103:433-437. [Was (is?) from http://fishbull.noaa.gov/1032/hewitt.pdf.] #' #' Hoenig, J.M. 1983. Empirical use of longevity data to estimate mortality rates. Fishery Bulletin. 82:898-903. [Was (is?) from http://www.afsc.noaa.gov/REFM/age/Docs/Hoenig_EmpiricalUseOfLongevityData.pdf.] @@ -108,7 +111,7 @@ #' Mmethods("tmax") #' #' ## Simple Examples -#' metaM("tmax",tmax=20) +#' metaM("HamelCope",tmax=20) #' metaM("HoenigNLS",tmax=20) #' metaM("HoenigNLS",tmax=20,verbose=FALSE) #' @@ -133,7 +136,7 @@ #' #' ## Example of multiple methods using Mmethods #' # select some methods -#' metaM(Mmethods()[-c(15,20,22:24,26:29)],K=K,Linf=Linf,Temp=Temp,tmax=tmax,t50=t50) +#' metaM(Mmethods()[-c(16,21,23:25,27:30)],K=K,Linf=Linf,Temp=Temp,tmax=tmax,t50=t50) #' # select just the Hoenig methods #' metaM(Mmethods("Hoenig"),K=K,Linf=Linf,Temp=Temp,tmax=tmax,t50=t50) #' @@ -150,7 +153,7 @@ Mmethods <- function(method=c("all","tmax","K","Hoenig","Pauly","FAMS")) { method <- match.arg(method) all_meth <- c("HoenigNLS","HoenigO","HoenigOF","HoenigOM","HoenigOC", "HoenigO2","HoenigO2F","HoenigO2M","HoenigO2C", - "HoenigLM","HewittHoenig","tmax1", + "HoenigLM","HewittHoenig","tmax1","HamelCope", "PaulyLNoT","PaulyL","PaulyW", "K1","K2","JensenK1","JensenK2","Gislason", "AlversonCarney","Charnov", @@ -161,7 +164,7 @@ Mmethods <- function(method=c("all","tmax","K","Hoenig","Pauly","FAMS")) { P_meth <- switch(method, all = { meths <- all_meth }, - tmax = { meths <- c("tmax1",H_meth)}, + tmax = { meths <- c("HamelCope","tmax1",H_meth)}, K = { meths <- c("K1","K2","JensenK1","JensenK2")}, Hoenig = { meths <- H_meth}, Pauly = { meths <- all_meth[grep("Pauly",all_meth)] }, @@ -191,6 +194,11 @@ metaM <- function(method=Mmethods(), metaM1 <- function(method,tmax,K,Linf,t0,b,L,Temp,t50,Winf,PS,...) { switch(method, + HamelCope = { ## from Hamel & Cope (2022), Equation 7 + name <- "Hamel and Cope (2022) tmax equation" + iCheck_tmax(tmax) + givens <- c(tmax=tmax) + M <- 5.40/tmax }, tmax1 = { ## from Then et al. (2015), Table 3, 1st line name <- "Then et al. (2015) tmax equation" iCheck_tmax(tmax) diff --git a/R/psdAdd.R b/R/psdAdd.R index 569d69e9..4010c326 100644 --- a/R/psdAdd.R +++ b/R/psdAdd.R @@ -6,6 +6,7 @@ #' @param species A character or factor vector that contains the species names. Ignored if \code{len} is a formula. #' @param group A named list that provides specific choices for \code{group} for species for which more than one set of Gabelhouse lengths exists in \code{\link{PSDlit}}. #' @param data A data.frame that minimally contains the length measurements and species names if \code{len} is a formula. +#' @param thesaurus A named list for providing alternative species names (the values in the list) that correspond to specific names in \code{PSDlit} (the names in the list). See details and examples. #' @param units A string that indicates the type of units used for the lengths. Choices are \code{mm} for millimeters (DEFAULT), \code{cm} for centimeters, and \code{in} for inches. #' @param use.names A logical that indicates whether the vector returned is numeric (\code{=FALSE}) or string (\code{=TRUE}; default) representations of the Gabelhouse lengths. See details. #' @param as.fact A logical that indicates that the new variable should be returned as a factor (\code{=TRUE}) or not (\code{=FALSE}). Defaults to same as \code{use.names} unless \code{addLens} is not \code{NULL}, in which case it will default to \code{FALSE}. See details. @@ -15,7 +16,9 @@ #' #' @details This computes a vector that contains the Gabelhouse lengths specific to each species for all individuals in an entire data frame. The vector can be appended to an existing data.frame to create a variable that contains the Gabelhouse lengths for each individual. The Gabelhouse length value will be \code{NA} for each individual for which Gabelhouse length definitions do not exist in \code{\link{PSDlit}}. Species names in the data.frame must be the same as those used in \code{\link{PSDlit}} (i.e., same spelling and capitalization; use \code{psdVal()} to see the list of species). #' -#' Some species have Gabelhouse lengths for sub-groups (e.g., \dQuote{lentic} vs \dQuote{lotic}). For these species, choose which sub-group to use with \code{group}. +#' The \code{thesaurus} argument may be used to relate alternate species names to the species names used in \code{PSDlit}. For example, you (or your data) may use \dQuote{Bluegill Sunfish}, but \dQuote{Bluegill} is used in \code{PSDlit}. The alternate species name can be used here if it is defined in a named vector (or list) given to \code{thesarus=}. The alternate species name is the value and the species name in \code{PSDlit} is the name in this vector/list - e.g., \code{c("Bluegill"="Bluegill Sunfish")}. See the examples for a demonstration. +#' +#' Some species have length categories separated by sub-group. For example, length categories exist for both lentic and lotic populations of Brown Trout. The length values for a sub-group may be obtained by either including the species name in \code{species} and the sub-group name in \code{group} or by using the combined species and sub-group name, with the sub-group name in parentheses, in \code{species}. Both methods are demonstrated in the examples. Note that an error is returned if a species has sub-groups but neither method is used to define the sub-group.#' #' #' Individuals shorter than \dQuote{stock} length will be listed as \code{substock} if \code{use.names=TRUE} or \code{0} if \code{use.names=FALSE}. #' @@ -42,63 +45,112 @@ #' @keywords manip #' #' @examples -#' #===== Create random data for three species -#' set.seed(345234534) -#' dbg <- data.frame(species=factor(rep(c("Bluegill"),30)), -#' tl=round(rnorm(30,130,50),0)) -#' dlb <- data.frame(species=factor(rep(c("Largemouth Bass"),30)), -#' tl=round(rnorm(30,350,60),0)) -#' dbt <- data.frame(species=factor(rep(c("Bluefin Tuna"),30)), -#' tl=round(rnorm(30,1900,300),0)) -#' df <- rbind(dbg,dlb,dbt) -#' -#' #===== Simple examples +#' #===== Simple examples -- 2 species, no groups, names as in PSDlit +#' #----- Isolate simple data from PSDWRtest +#' tmp <- subset(PSDWRtest, +#' species %in% c("Yellow Perch","Largemouth Bass"), +#' select=c("species","len")) +#' peek(tmp,n=6) +#' #' #----- Add variable using category names -- non-formula notation -#' df$PSD <- psdAdd(df$tl,df$species) -#' peek(df,n=6) +#' tmp$PSD <- psdAdd(tmp$len,tmp$species) +#' peek(tmp,n=6) #' #' #----- Add variable using category names -- formula notation -#' df$PSD1 <- psdAdd(tl~species,data=df) -#' peek(df,n=6) +#' tmp$PSD1 <- psdAdd(len~species,data=tmp) +#' peek(tmp,n=6) #' #' #----- Add variable using length values as names -#' # Also turned off messaging of fish not in PSDlit -#' df$PSD2 <- psdAdd(tl~species,data=df,use.names=FALSE,verbose=FALSE) -#' peek(df,n=6) +#' tmp$PSD2 <- psdAdd(len~species,data=tmp,use.names=FALSE) +#' peek(tmp,n=6) #' #' #----- Same as above but using dplyr #' if (require(dplyr)) { -#' df <- df %>% -#' mutate(PSD1A=psdAdd(tl,species,verbose=FALSE), -#' PSD2A=psdAdd(tl,species,use.names=FALSE,verbose=FALSE)) -#' peek(df,n=6) +#' tmp <- tmp %>% +#' mutate(PSD1A=psdAdd(len,species), +#' PSD2A=psdAdd(len,species,use.names=FALSE)) +#' peek(tmp,n=6) #' } #' -#' #===== Adding lengths besides the Gabelhouse lengths -#' #----- Add a "minimum length" for Bluegill -#' df$PSD3 <- psdAdd(tl~species,data=df,verbose=FALSE, -#' addLens=list("Bluegill"=c("minLen"=175))) -#' df$PSD3A <- psdAdd(tl~species,data=df,verbose=FALSE, -#' addLens=list("Bluegill"=175)) -#' df$PSD3B <- psdAdd(tl~species,data=df,verbose=FALSE, -#' addLens=list("Bluegill"=c("minLen"=175)),use.names=FALSE) -#' head(df,n=6) -#' -#' #----- Add add'l lengths and names for Bluegill and Largemouth Bass -#' df$psd4 <- psdAdd(tl~species,data=df,verbose=FALSE, -#' addLens=list("Bluegill"=175, -#' "Largemouth Bass"=c(254,356))) -#' peek(df,n=20) -#' -#' #===== Example for a species with sub-groups -#' dbt <- data.frame(species=factor(rep(c("Brown Trout"),30)), -#' tl=round(rnorm(30,230,50),0)) -#' dlt <- data.frame(species=factor(rep(c("Lake Trout"),30)), -#' tl=round(rnorm(30,550,60),0)) -#' df2 <- rbind(dbt,dlt) -#' -#' df2$psd <- psdAdd(tl~species,data=df2,group=list("Brown Trout"="lentic")) -#' peek(df2,n=6) +#' #===== Add lengths besides Gabelhouse lengths (start over with same simple data) +#' tmp <- subset(PSDWRtest, +#' species %in% c("Yellow Perch","Largemouth Bass"), +#' select=c("species","len")) +#' +#' #----- Add a "minimum length" for one species +#' tmp$PSD3 <- psdAdd(len~species,data=tmp, +#' addLens=list("Yellow Perch"=c("minLen"=225))) +#' tmp$PSD3A <- psdAdd(len~species,data=tmp, +#' addLens=list("Yellow Perch"=225)) +#' tmp$PSD3B <- psdAdd(len~species,data=tmp, +#' addLens=list("Yellow Perch"=c("minLen"=225)),use.names=FALSE) +#' head(tmp,n=6) +#' +#' #----- Add add'l lengths and names for multiple species +#' tmp$psd4 <- psdAdd(len~species,data=tmp, +#' addLens=list("Yellow Perch"=175, +#' "Largemouth Bass"=c(254,306))) +#' peek(tmp,n=20) +#' +#' #===== Handle additional species in PSDlit but named differently +#' #----- Isolate different species data from PSDWRtest +#' tmp <- subset(PSDWRtest, +#' species %in% c("Bluegill Sunfish","Lean Lake Trout"), +#' select=c("species","len")) +#' +#' #----- No "Bluegill Sunfish" in PSDlit, use thesaurus to note this is "Bluegill" +#' # Note: "Lean Lake Trout" not processed as not in PSDlit +#' tmp$psd5 <- psdAdd(len~species,data=tmp, +#' thesaurus=c("Bluegill"="Bluegill Sunfish")) +#' peek(tmp,n=6) +#' +#' #----- Process multiple species in PSDlit with different names +#' # Note: Can still use addLens=, but with original name +#' thes <- c("Bluegill"="Bluegill Sunfish","Lake Trout"="Lean Lake Trout") +#' tmp$psd6 <- psdAdd(len~species,data=tmp,thesaurus=thes) +#' tmp$psd7 <- psdAdd(len~species,data=tmp,thesaurus=thes, +#' addLens=list("Bluegill Sunfish"=c("minLen"=175))) +#' peek(tmp,n=20) +#' +#' #===== Example for a species with sub-groups but only one sub-group in data +#' #----- Isolate species data from PSDWRtest ... only Brook Trout has sub-group +#' tmp <- subset(PSDWRtest, +#' species %in% c("Yellow Perch","Brook Trout"), +#' select=c("species","len")) +#' +#' #----- This will err as Brook Trout has sub-groups in PSDlit (as message notes) +#' # tmp$psd8 <- psdAdd(len~species,data=tmp) +#' +#' #----- Can choose "overall" sub-group with group= +#' tmp$psd8 <- psdAdd(len~species,data=tmp, +#' group=list("Brook Trout"="overall")) +#' peek(tmp,n=10) +#' +#' #----- Or can create species name with sub-group name in parentheses +#' # Note: this is more useful in next examples +#' tmp$species2 <- ifelse(tmp$species=="Brook Trout","Brook Trout (overall)", +#' tmp$species) +#' tmp$psd8A <- psdAdd(len~species2,data=tmp) # note use of species2 +#' peek(tmp,n=10) +#' +#' #===== Example for species with more than one sub-group in data +#' #----- Isolate species data from PSDWRtest ... Brown Trout has two sub-groups +#' tmp <- subset(PSDWRtest, +#' species %in% c("Yellow Perch","Largemouth Bass","Brown Trout"), +#' select=c("species","len","location")) +#' peek(tmp,n=10) +#' +#' #----- Must create a species name variable with sub-groups in parentheses +#' # Note: there are likely many ways to do this specific to each use-case +#' tmp$species2 <- tmp$species +#' tmp$species2[tmp$species=="Brown Trout" & +#' tmp$location=="Trout Lake"] <- "Brown Trout (lotic)" +#' tmp$species2[tmp$species=="Brown Trout" & +#' tmp$location=="Brushy Creek"] <- "Brown Trout (lentic)" +#' peek(tmp,n=10) +#' +#' tmp$psd9 <- psdAdd(len~species2,data=tmp) +#' peek(tmp,n=10) #' #' @rdname psdAdd #' @export @@ -108,7 +160,8 @@ psdAdd <- function (len,...) { #' @rdname psdAdd #' @export -psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), +psdAdd.default <- function(len,species,thesaurus=NULL, + group=NULL,units=c("mm","cm","in"), use.names=TRUE, as.fact=ifelse(is.null(addLens),use.names,FALSE), addLens=NULL,verbose=TRUE,...) { @@ -118,10 +171,10 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), if (!inherits(species,c("character","factor"))) STOP("'species' must be character or factor.") ## Prepare the PSD literature values data frame - PSDlit <- FSA::PSDlit + PSDlit <- iPrepPSDlit(thesaurus) ## Find species that have known Gabelhouse lengths - # get list of species in data - specs <- unique(species) + # get list of species in data ... change from factor to character if necessary + specs <- as.character(unique(species)) GLHSspecs <- specs[specs %in% unique(PSDlit$species)] ## Create data.frames with species that are NA and w/o Gabelhouse lengths and ## one with Gabelhouse lengths. The loop below will then start with a @@ -130,7 +183,7 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), # - rownumbers is needed to get back the original order # - PSD will eventually have the Gabelhouse length categories data <- data.frame(len,species,rownums=seq_along(len),PSD=rep(NA,length(len))) - # data.frame where species is NA and doesn't have Gabelhousee length + # data.frame where species is NA and doesn't have Gabelhouse length ndata <- data[is.na(data$species) | !data$species %in% GLHSspecs,] if (verbose & nrow(ndata)>0) MESSAGE("Species in the data with no Gabelhouse (PSD) lengths in `PSDlit`: ", @@ -138,7 +191,7 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), # data.frame where species have Gabelhouse lengths ... make sure no NAs data <- data[data$species %in% GLHSspecs,] data <- data[!is.na(data$species),] - + ## Cycle through each species where PSD values are known, add PSD categories ## and append to data.frame that contained species w/o Gabelhouse lengths for (i in seq_along(GLHSspecs)) { @@ -150,10 +203,11 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), else tmpAddLens <- NULL # get the Gabelhouse length categories if (!is.null(group)) { - if (GLHSspecs[i] %in% names(group)) group <- group[[GLHSspecs[i]]] - else group <- NULL - } - glhse <- psdVal(GLHSspecs[i],group=group,units=units,addLens=tmpAddLens) + if (GLHSspecs[i] %in% names(group)) tmp_group <- group[[GLHSspecs[i]]] + else tmp_group <- NULL + } else tmp_group <- NULL + glhse <- psdVal(GLHSspecs[i],group=tmp_group,units=units,addLens=tmpAddLens, + dat=PSDlit) # computes the Gabelhouse length categories and adds to the data frame if (all(is.na(tmpdf$len))) { if (verbose) message("All values in 'len' were missing for ",GLHSspecs[i]) @@ -176,7 +230,8 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), #' @rdname psdAdd #' @export -psdAdd.formula <- function(len,data=NULL,group=NULL,units=c("mm","cm","in"), +psdAdd.formula <- function(len,data=NULL,thesaurus=NULL, + group=NULL,units=c("mm","cm","in"), use.names=TRUE, as.fact=ifelse(is.null(addLens),use.names,FALSE), addLens=NULL,verbose=TRUE,...) { @@ -196,6 +251,46 @@ psdAdd.formula <- function(len,data=NULL,group=NULL,units=c("mm","cm","in"), STOP("'len' must have one and only one factor variable (species)", " on right-hand-side.") ## Send to default method - psdAdd.default(tmp$mf[[tmp$Rpos]],tmp$mf[[tmp$EFactPos]],group,units, + psdAdd.default(tmp$mf[[tmp$Rpos]],tmp$mf[[tmp$EFactPos]],thesaurus,group,units, use.names,as.fact,addLens,verbose,...) } + + +# ============================================================================== +# Internal -- prepare PSDlit by loading it and replacing its default names with +# names in the thesaurus, if any +# ============================================================================== +iPrepPSDlit <- function(thesaurus) { + # Load PSDlit into dat in this function namespace + dat <- FSA::PSDlit + if (!is.null(thesaurus)) { + # Some sanity checks on thesaurus + if (!(is.vector(thesaurus) | is.list(thesaurus))) + STOP("'thesaurus' must be either a vector or list. ", + "Make sure it is not 'factor'ed.") + if (length(names(thesaurus))==0) + STOP("Values in 'thesaurus' must be named (with species names from 'PSDlit'.") + if (!is.character(thesaurus)) + STOP("Values in 'thesaurus' must be strings of species names.") + # thesaurus appears to be a named vector/list of strings ... start processing + # Alphabetize names in thesaurus to match PSDlit + thesaurus <- thesaurus[order(names(thesaurus))] + # Remove name from thesaurus if not in dat/PSDlit + thes.nokeep <- which(!names(thesaurus) %in% unique(dat$species)) + if (length(thes.nokeep)>0) { + MESSAGE("The following species names were in 'thesaurus' but do ", + "not have an entry in 'PSDlit' and will be ignored: ", + iStrCollapse(names(thesaurus)[thes.nokeep]),".") + thesaurus <- thesaurus[-thes.nokeep] + } + # Find dat/PSDlit species in kept thesaurus and change names to thesaurus names + if (length(thesaurus)>0) { + thes.pos <- which(dat$species %in% names(thesaurus)) + dat$species[thes.pos] <- unlist(thesaurus) + # Re-alphabetize dat/PSDlit + dat <- dat[order(dat$species),] + } + } + # Return dat/PSDlit + dat +} diff --git a/R/psdCalc.R b/R/psdCalc.R index a960fe22..18ee5674 100644 --- a/R/psdCalc.R +++ b/R/psdCalc.R @@ -48,51 +48,53 @@ #' @keywords hplot #' #' @examples -#' #===== Random length data for Yellow Perch (for example) to the nearest mm -#' set.seed(633437) -#' yepdf <- data.frame(yepmm=round(c(rnorm(100,mean=125,sd=15), -#' rnorm(50,mean=200,sd=25), -#' rnorm(20,mean=270,sd=40)),0), -#' species=rep("Yellow Perch",170)) -#' #' #===== Simple (typical) uses with just Gabelhouse lengths +#' tmp <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len")) +#' #' #----- All results -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch") +#' psdCalc(~len,data=tmp,species="Yellow Perch") #' #' #----- Just the traditional indices -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch",what="traditional") +#' psdCalc(~len,data=tmp,species="Yellow Perch",what="traditional") #' #' #----- Just the incremental indices -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch",what="incremental") +#' psdCalc(~len,data=tmp,species="Yellow Perch",what="incremental") #' #' #===== Add a custom length of interest (to the Gabelhouse lengths) -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch",addLens=150) +#' psdCalc(~len,data=tmp,species="Yellow Perch",addLens=150) #' #' #----- Additional lengths can be named -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch",addLens=c("minLen"=150)) -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch", +#' psdCalc(~len,data=tmp,species="Yellow Perch",addLens=c("minLen"=150)) +#' psdCalc(~len,data=tmp,species="Yellow Perch", #' addLens=c("minLen"=150,"maxslot"=275)) #' #' #----- Can return just those results that include the additional lengths -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch", +#' psdCalc(~len,data=tmp,species="Yellow Perch", #' addLens=c("minSlot"=150,"maxSlot"=275),justAdds=TRUE) -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch", +#' psdCalc(~len,data=tmp,species="Yellow Perch", #' addLens=c("minSlot"=150,"maxSlot"=275),justAdds=TRUE,what="traditional") #' #' #===== Can show intermediate values (num in category and in stock) -#' psdCalc(~yepmm,data=yepdf,species="Yellow Perch",showInterm=TRUE) +#' psdCalc(~len,data=tmp,species="Yellow Perch",showInterm=TRUE) +#' +#' #===== Some species require use of group +#' tmp <- subset(PSDWRtest,species=="Brown Trout" & location=="Trout Lake", +#' select=c("species","location","len")) +#' peek(tmp,n=6) #' -#' #===== Some species require use of group (e.g., treat these as if Brown Trout) -#' psdCalc(~yepmm,data=yepdf,species="Brown Trout",group="lotic") -#' psdCalc(~yepmm,data=yepdf,species="Brown Trout",group="lentic") +#' # will err because Brown Trout has sub-groups in PSDlit +#' # psdCalc(~len,data=tmp,species="Brown Trout") +#' psdCalc(~len,data=tmp,species="Brown Trout",group="lotic") +#' psdCalc(~len,data=tmp,species="Brown Trout (lotic)") #' #' #===== For species not in PSDlit ... don't include species and use addLens -#' # Note that these are same data as above, but treated as different species -#' psdCalc(~yepmm,data=yepdf,addLens=c("stock"=130,"quality"=200,"preferred"=250, -#' "memorable"=300,"trophy"=380)) +#' # Note these are same data as above, but treated as species not in PSDlit +#' psdCalc(~len,data=tmp,addLens=c("stock"=130,"quality"=200,"preferred"=250, +#' "memorable"=300,"trophy"=380)) #' #' @export psdCalc -psdCalc <- function(formula,data,species,group=NULL,units=c("mm","cm","in"), +psdCalc <- function(formula,data,species, + group=NULL,units=c("mm","cm","in"), method=c("multinomial","binomial"),conf.level=0.95, addLens=NULL,addNames=NULL,justAdds=FALSE, what=c("all","traditional","incremental","none"), @@ -105,8 +107,8 @@ psdCalc <- function(formula,data,species,group=NULL,units=c("mm","cm","in"), #----- Make sure species is not missing, or if it is that addLens have been given if (!missing(species)) { - brks <- psdVal(species,group,units=units,incl.zero=FALSE, - addLens=addLens,addNames=addNames) + brks <- psdVal(species,group=group,units=units, + incl.zero=FALSE,addLens=addLens,addNames=addNames) } else { # species is missing so must have an addLens if (is.null(addLens)) diff --git a/R/psdVal.R b/R/psdVal.R index 9ca7ea74..304e7a24 100644 --- a/R/psdVal.R +++ b/R/psdVal.R @@ -9,9 +9,12 @@ #' @param addLens A numeric vector that contains minimum length definitions for additional categories. See details. #' @param addNames A string vector that contains names for the additional length categories added with \code{addLens}. See details. #' @param showJustSource A logical that indicates whether just the literature source information should be returned (\code{TRUE}) or not. If \code{TRUE} this will NOT return any of the Gabelhouse length information. +#' @param dat Data.frame of Gabelhouse length categories for all species. Defaults to `PSDlit` and is generally not used by the user (this simplifies use of this function in \code{psdAdd}). #' #' @details Finds the Gabelhouse lengths from \code{data(PSDlit)} for the species given in \code{species}. The species name must be spelled exactly (including capitalization) as it appears in \code{data(PSDlit)}. Type \code{psdVal()} to see the list of species and how they are spelled. #' +#' Some species have length categories separated by sub-group. For example, length categories exist for both lentic and lotic populations of Brown Trout. The length values for a sub-group may be obtained by either including the species name in \code{species} and the sub-group name in \code{group} or by using the combined species and sub-group name, with the sub-group name in parentheses, in \code{species}. Both methods are demonstrated in the examples. Note that an error is returned if a species has sub-groups but neither method is used to define the sub-group.#' +#' #' A zero is included in the first position of the returned vector if \code{incl.zero=TRUE}. This is useful when computing PSD values with a data.frame that contains fish smaller than the stock length. #' #' Additional lengths may be added to the returned vector with \code{addLens}. Names for these lengths can be included as names in \code{addLens} or separately in \code{addNames}. If \code{addNames} is NULL and \code{addLens} is not named then the default category names will be the lengths from \code{addLens}. The \code{addLens} argument is useful for calculating PSD values that are different from the Gabelhouse lengths. @@ -47,10 +50,15 @@ #' psdVal("Bluegill",showJustSource=TRUE) #' #' #===== For species that have sub-groups +#' #----- using group= argument #' psdVal("Brown Trout",group="lentic") #' psdVal("Brown Trout",group="lotic") -#' psdVal("Palmetto Bass",group="revised") -#' psdVal("Palmetto Bass",group="original") +#' #----- group combined in species name, so no group= use +#' psdVal("Brown Trout (lentic)") +#' +#' #===== For species with revised values +#' psdVal("Palmetto Bass") +#' psdVal("Palmetto Bass (original)") #' #' #===== Adding user-defined categories #' #----- with lengths and names separately in addLens= and addNames= @@ -60,28 +68,29 @@ #' #----- with a named vector in addLens= #' psdVal("Bluegill",units="in",addLens=c("MinLen"=7)) #' psdVal("Bluegill",units="in",addLens=c("MinSlot"=7,"MaxSlot"=9)) -#' +#' #' @export psdVal psdVal <- function(species="List",group=NULL,units=c("mm","cm","in"), addLens=NULL,addNames=NULL, - incl.zero=TRUE,showJustSource=FALSE) { + incl.zero=TRUE,showJustSource=FALSE,dat=NULL) { units <- match.arg(units) - #====== Load PSDlit into this function's environment, do some checking, and - # return a data.frame with infor for just that species/group - PSDlit <- FSA::PSDlit - PSDlit <- iPSDGetSpecies(PSDlit,species,group) + + #====== If dat is null then load PSDlit into dat ... then do some checking, + # and return a data.frame with info for just that species/group + if (is.null(dat)) dat <- FSA::PSDlit + dat <- iPSDGetSpecies(dat,species,group) - #====== Prepare Result as longs as PSDlit was not returned as NULL - if (!is.null(PSDlit)) { + #====== Prepare Result as longs as dat was not returned as NULL + if (!is.null(dat)) { if (showJustSource) { ifelse(is.null(group),cols <- c(1,14),cols <- c(1,2,15)) - PSDlit[,cols] + dat[,cols] } else { #----- Identify columns based on units ifelse(units=="in",cols <- 3:8,cols <- 9:14) if (is.null(group)) cols <- cols-1 #----- get the length categories - PSDvec <- as.matrix(PSDlit[,cols])[1,] + PSDvec <- as.matrix(dat[,cols])[1,] names(PSDvec) <- gsub("\\..*","",names(PSDvec)) #----- remove zero category (substock) if asked if (!incl.zero) PSDvec <- PSDvec[!names(PSDvec)=="substock"] @@ -109,7 +118,6 @@ psdVal <- function(species="List",group=NULL,units=c("mm","cm","in"), } } - # ============================================================================== # Internal -- check species name against the 'dat' data.frame (usually PSDLit) # ============================================================================== diff --git a/R/wrAdd.R b/R/wrAdd.R index 22265c49..7f5a530e 100644 --- a/R/wrAdd.R +++ b/R/wrAdd.R @@ -6,6 +6,10 @@ #' #' The species names in \code{species} must match the spelling and capitalization of \code{species} in \code{\link{WSlit}}. Use \code{wsVal()} to see a list of all species for which standard weight equations exist in \code{\link{WSlit}} and, more importantly, how the species names are spelled and capitalized. #' +#' The \code{thesaurus} argument may be used to relate alternate species names to the species names used in \code{WSlit}. For example, you (or your data) may use \dQuote{Bluegill Sunfish}, but \dQuote{Bluegill} is used in \code{WSlit}. The alternate species name can be used here if it is defined in a named vector (or list) given to \code{thesarus=}. The alternate species name is the value and the species name in \code{PSDlit} is the name in this vector/list - e.g., \code{c("Bluegill"="Bluegill Sunfish")}. See the examples for a demonstration. +#' +#' Some species have length categories separated by sub-group. For example, length categories exist for both lentic and lotic populations of Brown Trout. The length values for a sub-group may be obtained by either including the species name in \code{species} and the sub-group name in \code{group} in \code{WsOpts} or by using the combined species and sub-group name, with the sub-group name in parentheses, in \code{species}. Both methods are demonstrated in the examples. Note that an error is returned if a species has sub-groups but neither method is used to define the sub-group. +#' #' Some (few) species have more than one equation listed in \code{\link{WSlit}} (for the specified units). In these instances the user must select one of the equations to use with \code{WsOpts}. \code{WsOpts} is a list of lists where the inside list contains one or more of \code{group}, \code{ref}, or \code{method} (see \code{\link{WSlit}}) required to specify a single equation for a particular species, which is the name of the inner list. See the examples for an illustration of how to use \code{WsOpts}. #' #' See examples and \href{https://fishr-core-team.github.io/FSA/articles/Computing_Relative_Weights.html}{this article} for a demonstration. @@ -14,6 +18,7 @@ #' @param len A numeric vector that contains length measurements. Not used if \code{wt} is a formula. #' @param spec A character or factor vector that contains the species names. Not used if \code{wt} is a formula. #' @param data A data.frame that minimally contains variables of the the observed lengths, observed weights, and the species names given in the \code{formula=}. +#' @param thesaurus A named list for providing alternative species names (the values in the list) that correspond to specific names in \code{PSDlit} (the names in the list). See details and examples. #' @param units A string that indicates whether the weight and length data in \code{formula} are in \code{"metric"} (DEFAULT; mm and g) or \code{"English"} (in and lbs) units. #' @param WsOpts A named list that provides specific choices for \code{group}, \code{ref}, or \code{method} for species for which more than one standard weight equation exists in \code{\link{WSlit}}. #' @param \dots Not used. @@ -31,51 +36,78 @@ #' @keywords manip #' #' @examples -#' #===== Create random data for three species -#' #----- just to control the randomization -#' set.seed(345234534) -#' dbt <- data.frame(species=factor(rep(c("Bluefin Tuna"),30)), -#' tl=round(rnorm(30,1900,300),0)) -#' dbt$wt <- round(4.5e-05*dbt$tl^2.8+rnorm(30,0,6000),1) -#' dbg <- data.frame(species=factor(rep(c("Bluegill"),30)), -#' tl=round(rnorm(30,130,50),0)) -#' dbg$wt <- round(4.23e-06*dbg$tl^3.316+rnorm(30,0,10),1) -#' dlb <- data.frame(species=factor(rep(c("Largemouth Bass"),30)), -#' tl=round(rnorm(30,350,60),0)) -#' dlb$wt <- round(2.96e-06*dlb$tl^3.273+rnorm(30,0,60),1) -#' df <- rbind(dbt,dbg,dlb) -#' str(df) -#' -#' #===== Add Wr variable -#' #----- using formula interface -#' df$Wr1 <- wrAdd(wt~tl+species,data=df) +#' #===== Simple example with 3 species, 2 in WSlit ... nothing unusual +#' tmp <- subset(PSDWRtest, +#' species %in% c("Yellow Perch","Iowa Darter","Largemouth Bass"), +#' select=c("species","len","wt")) +#' peek(tmp,n=10) #' +#' #----- Add Wr variable ... using formula interface +#' tmp$wr1 <- wrAdd(wt~len+species,data=tmp) #' #----- same but with non-formula interface -#' df$Wr2 <- wrAdd(df$wt,df$tl,df$species) -#' +#' tmp$wr2 <- wrAdd(tmp$wt,tmp$len,tmp$species) #' #----- same but using dplyr #' if (require(dplyr)) { -#' df <- df %>% -#' mutate(Wr3=wrAdd(wt,tl,species)) +#' tmp <- tmp %>% +#' mutate(wr3=wrAdd(wt,len,species)) #' } -#' #' #----- examine results -#' peek(df,n=10) -#' -#' #===== Example with only one species in the data.frame -#' bg <- droplevels(subset(df,species=="Bluegill")) -#' bg$Wr4 <- wrAdd(wt~tl+species,data=bg) -#' bg +#' peek(tmp,n=10) +#' +#' #===== Simple example with only one species in the data.frame +#' tmp <- subset(PSDWRtest,species %in% c("Yellow Perch"), +#' select=c("species","len","wt")) +#' tmp$wr <- wrAdd(wt~len+species,data=tmp) +#' peek(tmp,n=6) +#' +#' #===== Example of species with sub-groups but only 1 sub-group in data.frame +#' #----- Group not in species name so must specify group with WsOpts +#' tmp <- subset(PSDWRtest,species=="Brown Trout" & location=="Trout Lake", +#' select=c("species","len","wt")) +#' tmp$wr1 <- wrAdd(wt~len+species,data=tmp, +#' WsOpts=list("Brown Trout"=list("group"="lotic"))) +#' +#' #----- Group in species name so don't specify group with WsOpts +#' tmp$species2 <- "Brown Trout (lotic)" +#' tmp$wr2 <- wrAdd(wt~len+species2,data=tmp) # note use of species2 +#' +#' peek(tmp,n=6) +#' +#' #===== Example of species with sub-groups and 2 sub-groups in data.frame +#' tmp <- subset(PSDWRtest,species=="Brown Trout", +#' select=c("species","location","len","wt")) +#' #----- Must create "species" with sub-groups in name +#' #----- Many ways to do this, this is just one example for this case +#' tmp$species2 <- ifelse(tmp$location=="Trout Lake", +#' "Brown Trout (lotic)","Brown Trout (lentic)") +#' tmp$wr <- wrAdd(wt~len+species2,data=tmp) # note use of species2 +#' peek(tmp,n=6) #' -#' #===== Example with a species that has Ws eqns for multiple groups and a -#' # group needs to be specified with WsOpts -#' wae <- data.frame(species=factor(rep(c("Walleye"),30)), -#' tl=round(rnorm(30,500,200),0)) -#' wae$wt <- round(3.33e-06*wae$tl^3.16+rnorm(30,0,50),1) -#' # wae$Wr <- wrAdd(wt~tl+species,data=wae) # will err b/c multiple groups -#' wae$Wr <- wrAdd(wt~tl+species,data=wae, -#' WsOpts=list(Walleye=list(group="overall"))) -#' peek(wae,n=10) +#' #===== Example of a species name that needs the thesaurus +#' tmp <- subset(PSDWRtest,species %in% c("Yellow Perch","Bluegill Sunfish"), +#' select=c("species","len","wt")) +#' #----- Below will not add wr for "Bluegill Sunfish" as not in WsLit ("Bluegill" is) +#' tmp$wr1 <- wrAdd(wt~len+species,data=tmp) +#' #----- Use thesaurus to identify "Bluegill Sunfish" as "Blueill +#' tmp$wr2 <- wrAdd(wt~len+species,data=tmp,thesaurus=c("Bluegill"="Bluegill Sunfish")) +#' peek(tmp,n=10) +#' +#' #===== Example of species that has Ws eqns for multiple reference values +#' tmp <- subset(PSDWRtest,species=="Ruffe",select=c("species","len","wt")) +#' #----- Below will err as Ruffe has Ws eqns for multiple reference values +#' # tmp$wr <- wrAdd(wt~len+species,data=tmp) +#' #----- Must choose which eqn to use with WsOpts +#' tmp$wr <- wrAdd(wt~len+species,data=tmp, +#' WsOpts=list(Ruffe=list(ref=75))) +#' peek(tmp,n=6) +#' +#' #===== Example with two uses of WsOpts (and one species without) +#' tmp <- subset(PSDWRtest,species %in% c("Ruffe","Muskellunge","Iowa Darter"), +#' select=c("species","len","wt")) +#' tmp$wr <- wrAdd(wt~len+species,data=tmp, +#' WsOpts=list(Muskellunge=list(group="overall"), +#' Ruffe=list(ref=75))) +#' peek(tmp,n=10) #' #' @rdname wrAdd #' @export @@ -85,7 +117,7 @@ wrAdd <- function (wt,...) { #' @rdname wrAdd #' @export -wrAdd.default <- function(wt,len,spec, +wrAdd.default <- function(wt,len,spec,thesaurus=NULL, units=c("metric","English"),WsOpts=NULL,...) { ###### Internal Function #===== Print error if no options given, but they are needed @@ -94,7 +126,7 @@ wrAdd.default <- function(wt,len,spec, print(df[,c("species","group","ref","method")]) #----- Error message for next two possible problems STOP("More than one Ws equation exists for ",iStrCollapse(unique(df$species)), - ". Please use a named list in 'opts=' to select one ", + ". Please use a named list in 'WsOpts=' to select one ", "equation for ",iStrCollapse(unique(df$species))," by specifing 'group', ", "'ref', or 'method' as appropriate. See details in documentation ", "and above (for reference).") @@ -107,7 +139,7 @@ wrAdd.default <- function(wt,len,spec, #----- Reduce Wsdf to just for that species Wsdf <- droplevels(Wsdf[Wsdf$species==species,]) #----- If >1 Ws eqn for species/units, then need user to further define - # with opts, otherise one Ws eqn is returned + # with opts, otherwise one Ws eqn is returned if (nrow(Wsdf)>1) { # ..... Need opts for species but none given (at all) so STOP if (is.null(WsOpts)) iErrOpts(Wsdf) @@ -126,8 +158,8 @@ wrAdd.default <- function(wt,len,spec, Wsdf <- droplevels(Wsdf[Wsdf[[names(tmp)]]==tmp,]) if (nrow(Wsdf)==0) STOP("Use of '",crit_opts[i],"=",tmp[[1]],"' for ",iStrCollapse(species), - " did not return a standard weight equation. Please reconsider your use ", - "of 'WsOpts=' to restrict to only one equation for ", + " did not return a standard weight equation. Please reconsider your ", + "use of 'WsOpts=' to restrict to only one equation for ", iStrCollapse(species),".") else if (nrow(Wsdf)>1) { #..... send error if not reduced to only one Ws equation @@ -143,7 +175,6 @@ wrAdd.default <- function(wt,len,spec, #----- Return appropriate part of Wsdf (i.e., WSlit) Wsdf } - ###### END Internal Function ###### BEGIN Main Function @@ -156,7 +187,7 @@ wrAdd.default <- function(wt,len,spec, #===== Prepare the Ws literature values data frame #----- load WSlit data frame into this functions environment - WSlit <- FSA::WSlit + WSlit <- iPrepWSlit(thesaurus) #----- isolate only those data for which those units exist WSlit <- droplevels(WSlit[WSlit$units==units,]) @@ -166,8 +197,8 @@ wrAdd.default <- function(wt,len,spec, Wr=rep(NA,length(len))) #===== Initiate a blank new data frame with same columns as old data frame ndata <- data[-c(seq_len(nrow(data))),] - #===== get list of species in data - specs <- unique(spec) + #===== get list of species in data ... change from factor to character if necessary + specs <- as.character(unique(spec)) #===== cycle through each species where WS equations are known for (i in seq_along(specs)) { @@ -199,7 +230,7 @@ wrAdd.default <- function(wt,len,spec, #' @rdname wrAdd #' @export -wrAdd.formula <- function(wt,data,units=c("metric","English"),...) { +wrAdd.formula <- function(wt,data,thesaurus=NULL,units=c("metric","English"),...) { #===== Perform some checks on the formula tmp <- iHndlFormula(wt,data,expNumR=1,expNumE=2,expNumENums=1,expNumEFacts=1) if (tmp$vnum!=3) STOP("'wt' must have one variable on the left-hand-side ", @@ -215,5 +246,44 @@ wrAdd.formula <- function(wt,data,units=c("metric","English"),...) { #===== Call the wrAdd.default wrAdd.default(tmp$mf[,tmp$Rpos],tmp$mf[,tmp$ENumPos], - tmp$mf[,tmp$EFactPos],units,...) + tmp$mf[,tmp$EFactPos],thesaurus,units,...) } + +# ============================================================================== +# Internal -- prepare WSlit by loading it and replacing its default names with +# names in the thesaurus, if any +# ============================================================================== +iPrepWSlit <- function(thesaurus) { + # Load WSlit into dat in this function namespace + dat <- FSA::WSlit + if (!is.null(thesaurus)) { + # Some sanity checks on thesaurus + if (!(is.vector(thesaurus) | is.list(thesaurus))) + STOP("'thesaurus' must be either a vector or list. ", + "Make sure it is not 'factor'ed.") + if (length(names(thesaurus))==0) + STOP("Values in 'thesaurus' must be named (with species names from 'WSlit'.)") + if (!is.character(thesaurus)) + STOP("Values in 'thesaurus' must be strings of species names.") + # thesaurus appears to be a named vector/list of strings ... start processing + # Alphabetize names in thesaurus to match dat/WSlit + thesaurus <- thesaurus[order(names(thesaurus))] + # Remove name from thesaurus if not in dat/WSlit + thes.nokeep <- which(!names(thesaurus) %in% unique(dat$species)) + if (length(thes.nokeep)>0) { + MESSAGE("The following species names were in 'thesaurus' but do ", + "not have an entry in 'WSlit' and will be ignored: ", + iStrCollapse(names(thesaurus)[thes.nokeep]),".") + thesaurus <- thesaurus[-thes.nokeep] + } + # Find species in dat/PSDlit in kept thesaurus and change names to thesaurus names + if (length(thesaurus)>0) { + tmp <- match(dat$species,names(thesaurus)) + thes.pos <- which(!is.na(tmp)) + dat$species[thes.pos] <- unname(thesaurus[tmp[thes.pos]]) + } + } + # Return dat/WSlit + dat +} + diff --git a/R/wsVal.R b/R/wsVal.R index 87a8801b..dba9b5e2 100644 --- a/R/wsVal.R +++ b/R/wsVal.R @@ -10,6 +10,8 @@ #' #' Note from above that the coefficients are returned for the TRANSFORMED model. Thus, to obtain the standard weight (Ws), the returned coefficients are used to compute the common log of Ws which must then be raised to the power of 10 to compute the Ws. #' +#' Some species have length categories separated by sub-group. For example, length categories exist for both lentic and lotic populations of Brown Trout. The length values for a sub-group may be obtained by either including the species name in \code{species} and the sub-group name in \code{group} or by using the combined species and sub-group name, with the sub-group name in parentheses, in \code{species}. Both methods are demonstrated in the examples. Note that an error is returned if a species has sub-groups but neither method is used to define the sub-group. +#' #' See examples and \href{https://fishr-core-team.github.io/FSA/articles/Computing_Relative_Weights.html}{this article} for a demonstration. #' #' @param species A string that contains the species name for which to find Ws coefficients. See details. @@ -18,6 +20,7 @@ #' @param ref A numeric that indicates which percentile the equation should be returned for. Note that the vast majority of equations only exist for the \code{75}th percentile (DEFAULT). #' @param method A string that indicates which equation-derivation method should be used (one of \code{"RLP"}, \code{"EmP"}, or \code{"Other"}). Defaults to \code{NULL} which will result in the only method available being returned or an error asking the user to choose a method for equations for which more than one method is available (which is the case for very few species). #' @param simplify A logical that indicates whether the \sQuote{units}, \sQuote{ref}, \sQuote{measure}, \sQuote{method}, \sQuote{comments}, and \sQuote{source} fields should be included (\code{=FALSE}) or not (\code{=TRUE}; DEFAULT). See details. +#' @param dat Data.frame of Gabelhouse length categories for all species. Defaults to `WSlit` and is generally not used by the user (this simplifies use of this function in \code{wrAdd}). #' #' @return A one row data frame from \code{\link{WSlit}} that contains all known information about the standard weight equation for a given species, type of measurement units, and reference percentile if \code{simplify=FALSE}. If \code{simplify=TRUE} then only the species; minimum and maximum length for which the standard equation should be applied; and intercept, slope, and quadratic coefficients for the standard weight equation. Note that the maximum length and the quadratic coefficient will not be returned if they do not exist in \code{\link{WSlit}} for the species. #' @@ -37,90 +40,91 @@ #' #===== List all available Ws equations #' wsVal() #' -#' #===== Find equations for Bluegill, in different formats -#' wsVal("Bluegill") -#' wsVal("Bluegill",units="metric") -#' wsVal("Bluegill",units="English") -#' wsVal("Bluegill",units="English",simplify=TRUE) -#' -#' #===== Find equation for Cutthroat Trout, demonstrating use of group -#' wsVal("Cutthroat Trout",group="lotic") -#' wsVal("Cutthroat Trout",group="lentic") +#' #===== Find equations for Yellow Perch, in different formats +#' wsVal("Yellow Perch") +#' wsVal("Yellow Perch",units="metric") # same as default +#' wsVal("Yellow Perch",units="English") +#' wsVal("Yellow Perch",units="English",simplify=TRUE) #' #' #===== Find equation for Ruffe, demonstrating quadratic formula #' wsVal("Ruffe",units="metric",ref=75,simplify=TRUE) #' wsVal("Ruffe",units="metric",ref=50,simplify=TRUE) #' +#' #===== Find equation for Brown Trout, which has equations for sub-groups +#' #----- demonstrating use of group= argument +#' wsVal("Brown Trout",group="lotic") +#' wsVal("Brown Trout",group="lentic") +#' #----- demonstrating group combined in species name, so no group= arg +#' wsVal("Brown Trout (lotic)") +#' wsVal("Brown Trout (lentic)") +#' #' #===== Add Ws & Wr values to a data frame (for one species) ... also see wrAdd() -#' #----- Get Ws equation info -#' wsBG <- wsVal("Bluegill",units="metric") -#' wsBG +#' #----- Example data from PSDWRtest, simplify variables for this example +#' yepdf <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len","wt")) +#' str(yepdf) #' -#' #----- Get example data -#' data(BluegillLM,package="FSAdata") -#' str(BluegillLM) +#' #----- Get Ws equation info +#' ( wsYEP <- wsVal("Yellow Perch",units="metric") ) #' -#' #----- Add Ws (eqn is on log10-log10 scale ... so log10 len, 10^ result) -#' BluegillLM$ws <- 10^(wsBG[["int"]]+wsBG[["slope"]]*log10(BluegillLM$tl)) +#' #----- Add Ws (eqn is on log10-log10 scale ... so log10 length, 10^ result) +#' yepdf$ws <- 10^(wsYEP[["int"]]+wsYEP[["slope"]]*log10(yepdf$len)) #' #' #----- Change Ws for fish less than min.TL to NA -#' BluegillLM$ws[BluegillLM$tl% -#' mutate(ws=10^(wsBG[["int"]]+wsBG[["slope"]]*log10(tl)), -#' ws=ifelse(tl% filter(species=="Yellow Perch") %>% select(species,len,wt) %>% +#' mutate(ws=10^(wsYEP[["int"]]+wsYEP[["slope"]]*log10(len)), +#' ws=ifelse(len1) STOP("'species' must contain only one name.") - if (species=="List") iListSpecies(WSlit) + if (species=="List") iListSpecies(dat) else { #===== Make checks on species - #----- Species given, make sure in WSlit, then reduce data.frame to that species - if (!any(unique(WSlit$species)==species)) { + #----- Species given, make sure in dat/WSlit, then reduce data.frame to that species + if (!any(unique(dat$species)==species)) { tmp <- paste0("There is no Ws equation in 'WSlit' for ",iStrCollapse(species),".") - if (any(unique(WSlit$species)==capFirst(species))) + if (any(unique(dat$species)==capFirst(species))) STOP(tmp," However, there is an entry for ",iStrCollapse(capFirst(species)), " (note spelling, including capitalization).\n\n") else STOP(tmp," Type 'wsVal()' to see a list of available species.\n\n") - } else df <- droplevels(WSlit[WSlit$species==species,]) + } else df <- droplevels(dat[dat$species==species,]) #===== Determine if "group"s for that species and then handle if (any(!is.na(df$group))) { - #----- There are groups in WSlit, user did not supply group= so stop + #----- There are groups in dat/WSlit, user did not supply group= so stop if (is.null(group)) STOP(iStrCollapse(species)," has Ws equations for these sub-groups: ", iStrCollapse(unique(df$group)), ". Please use 'group=' to select the equation for one of these groups.\n\n") - #----- There are groups in WSlit, user supplied group=, is it good? + #----- There are groups in dat/WSlit, user supplied group=, is it good? if (!group %in% unique(df$group)) STOP("There is no ",iStrCollapse(group)," group for ",iStrCollapse(species), ". Please select from one of these groups: ", iStrCollapse(unique(df$group),last="or"),".\n\n") - #----- There are groups in WSlit, user supplied group= is good, reduce df + #----- There are groups in dat/WSlit, user supplied group= is good, reduce df df <- droplevels(df[df$group==group,]) } else { - #----- There are no groups in WSlit ... check if user supplied group= + #----- There are no groups in dat/WSlit ... check if user supplied group= if (!is.null(group)) WARN("There are no groups for ",iStrCollapse(species), "; thus, your 'group=' has been ignored.") #---- drop group variable from df @@ -129,7 +133,7 @@ wsVal <- function(species="List",group=NULL, #===== Checks on method tmp <- unique(df$method) - #----- If more than one method in WSlit but method NULL then force a choice + #----- If more than one method in dat/WSlit but method NULL then force a choice # otherwise (i.e., one method and method NULL) then continue with df if (is.null(method) & length(tmp)>1) STOP("Ws equations exist for both the RLP and EmP 'method's for ", @@ -151,7 +155,7 @@ wsVal <- function(species="List",group=NULL, #===== Make checks on ref (if OK reduce data frame to that ref) tmp <- unique(df$ref) - #----- If more than one ref in WSlit but ref is NULL then force a choice + #----- If more than one ref in dat/WSlit but ref is NULL then force a choice # otherwise (i.e., one ref and ref is NULL) then continue with df if (is.null(ref) & length(tmp)>1) STOP("Ws equations exist for more than one 'ref'erence value for ", @@ -183,4 +187,4 @@ wsVal <- function(species="List",group=NULL, df <- df[,names(df) %in% c("species",tmp,"int","slope","quad")] df } -} +} \ No newline at end of file diff --git a/_pkgdown.yml b/_pkgdown.yml index 63171905..c0c12647 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -138,6 +138,7 @@ reference: - PikeNY - PikeNYPartial1 - PSDlit + - PSDWRtest - SMBassLS - SMBassWB - SpotVA1 diff --git a/cran-comments/cran-comments-v0_10_1.md b/cran-comments/cran-comments-v0_10_1.md new file mode 100644 index 00000000..02261ad4 --- /dev/null +++ b/cran-comments/cran-comments-v0_10_1.md @@ -0,0 +1,10 @@ +* This updates the existing FSA package on CRAN with changes described in NEWS and minor changes. + +## Notes +* There may be a note about "fishR" being misspelled in the description. This is not a misspelling. + +## Testing Environments +* My Windows machine. +* Win Builder -- old-release, release, and development. +* Mac Builder +* GitHub Action (R-CMD-check.yaml) diff --git a/data-raw/PSDlit.csv b/data-raw/PSDlit.csv index 473af9fd..48794fe8 100644 --- a/data-raw/PSDlit.csv +++ b/data-raw/PSDlit.csv @@ -1,4 +1,5 @@ species,group,substock.in,stock.in,quality.in,preferred.in,memorable.in,trophy.in,substock.cm,stock.cm,quality.cm,preferred.cm,memorable.cm,trophy.cm,source +Alabama Bass,NA,0,7,11,14,17,20,0,18,28,35,43,51,Sammons et al. (2025) Arctic Grayling,NA,0,8,12,16,20,22,0,20,30,40,50,55,Hyatt (2000) Bighead Carp,NA,0,11.75,21.25,26.75,35,43.75,0,30,54,68,89,111,Phelps and Willis (2013) Bigmouth Buffalo,NA,0,11,18,24,30,37,0,28,46,61,76,94,Bister et al. (2000) @@ -10,17 +11,26 @@ Bluegill,NA,0,3,6,8,10,12,0,8,15,20,25,30,Gabelhouse (1984a) Brook Trout,overall,0,8,12,16,20,24,0,20,30,40,50,60,Hyatt (2000) Brook Trout,lentic,0,8,13,NA,NA,NA,0,20,33,NA,NA,NA,Anderson (1980) Brook Trout,lotic,0,5,8,NA,NA,NA,0,13,20,NA,NA,NA,Anderson (1980) +Brook Trout (overall),NA,0,8,12,16,20,24,0,20,30,40,50,60,Hyatt (2000) +Brook Trout (lentic),NA,0,8,13,NA,NA,NA,0,20,33,NA,NA,NA,Anderson (1980) +Brook Trout (lotic),NA,0,5,8,NA,NA,NA,0,13,20,NA,NA,NA,Anderson (1980) Brown Bullhead,NA,0,5,8,11,14,17,0,13,20,28,36,43,Bister et al. (2000) Brown Trout,lentic,0,8,12,16,20,24,0,20,30,40,50,60,Hyatt and Hubert (2001) Brown Trout,lotic,0,6,9,12,15,18,0,15,23,30,38,46,Milewski and Brown (1994) +Brown Trout (lentic),NA,0,8,12,16,20,24,0,20,30,40,50,60,Hyatt and Hubert (2001) +Brown Trout (lotic),NA,0,6,9,12,15,18,0,15,23,30,38,46,Milewski and Brown (1994) Bull Trout,NA,0,8,16,20,26,31,0,20,40,50,65,80,Hyatt (2000) Burbot,NA,0,8,15,21,26,32,0,20,38,53,67,82,Fisher et al. (1996) Chain Pickerel,NA,0,10,15,20,25,30,0,25,38,51,63,76,Gabelhouse (1984a) Channel Catfish,NA,0,11,16,24,28,36,0,28,41,61,71,91,Gabelhouse (1984a) Chinook Salmon,landlocked,0,11,18,24,30,37,0,28,46,61,76,94,Hill and Duffy (1993) +Chinook Salmon (landlocked),NA,0,11,18,24,30,37,0,28,46,61,76,94,Hill and Duffy (1993) Common Carp,NA,0,11,16,21,26,33,0,28,41,53,66,84,Gabelhouse (1984a) Cutthroat Trout,NA,0,8,14,18,24,30,0,20,35,45,60,75,Kruse and Hubert (1997) +Cutthroat Trout (lentic),NA,0,8,14,18,24,30,0,20,35,45,60,75,Kruse and Hubert (1997) +Cutthroat Trout (lotic),NA,0,8,14,18,24,30,0,20,35,45,60,75,Kruse and Hubert (1997) Flathead Catfish,NA,0,14,20,28,34,40,0,35,51,71,86,102,Quinn (1991) +Flier,NA,0,3,5,6,7,9,0,8,13,15,18,23,Bonvechio et al (2025) Freshwater Drum,NA,0,8,12,15,20,25,0,20,30,38,51,63,Gabelhouse (1984a) Gizzard Shad,NA,0,7,11,NA,NA,NA,0,18,28,NA,NA,NA,Anderson and Gutreuter (1983) Golden Trout,NA,0,8,10,14,18,22,0,20,25,35,45,55,Hyatt (2000) @@ -31,16 +41,26 @@ Kokanee,NA,0,8,10,12,16,20,0,12,25,30,40,50,Hyatt (2000) Lake Chubsucker,NA,0,4,7,10,11,14,0,11,18,24,28,35,Bonvechio and Bonvechio (2021) Lake Trout,NA,0,12,20,26,31,39,0,30,50,65,80,100,Hubert et al. (1994) Largemouth Bass,NA,0,8,12,15,20,25,0,20,30,38,51,63,Gabelhouse (1984a) +Longear Sunfish,NA,0,2.5,4,5,7,8.25,0,6,10,13,17,21,Miller et al. (2025) Longnose Gar,NA,0,16,27,36,45,55,0,41,69,91,114,140,Bister et al. (2000) Muskellunge,NA,0,20,30,38,42,50,0,51,76,97,107,127,Gabelhouse (1984a) +Muskellunge (overall),NA,0,20,30,38,42,50,0,51,76,97,107,127,Gabelhouse (1984a) +Muskellunge (female),NA,0,20,30,38,42,50,0,51,76,97,107,127,Gabelhouse (1984a) +Muskellunge (male),NA,0,20,30,38,42,50,0,51,76,97,107,127,Gabelhouse (1984a) Northern Pike,NA,0,14,21,28,34,44,0,35,53,71,86,112,Gabelhouse (1984a) +Northern Pikeminnow,NA,0,7,10,14,16,20,0,17,26,35,41,51,Voss and Quist (2025) Northern Snakehead,NA,0,7.5,13,16.5,22,27.5,0,19,34,42,55,70,Kim et al. (2019) Paddlefish,NA,0,16,26,33,41,51,0,41,66,84,104,130,Brown and Murphy (1993) +Paddlefish (overall),NA,0,16,26,33,41,51,0,41,66,84,104,130,Brown and Murphy (1993) +Paddlefish (female),NA,0,16,26,33,41,51,0,41,66,84,104,130,Brown and Murphy (1993) +Paddlefish (male),NA,0,16,26,33,41,51,0,41,66,84,104,130,Brown and Murphy (1993) Pallid Sturgeon,NA,0,13,25,33,41,50,0,33,63,84,104,147,Shuman et al. (2006) -Palmetto Bass,revised,0,10,16,20,24,28,0,25,41,51,61,71,Dumont and Neely (2011) -Palmetto Bass,original,0,8,12,15,20,25,0,20,30,38,51,63,Gabelhouse (1984a) +Palmetto Bass,NA,0,10,16,20,24,28,0,25,41,51,61,71,Dumont and Neely (2011) +Palmetto Bass (original),NA,0,8,12,15,20,25,0,20,30,38,51,63,Gabelhouse (1984a) Pumpkinseed,NA,0,3,6,8,10,12,0,8,15,20,25,30,Gabelhouse (1984a) Rainbow Trout,NA,0,10,16,20,26,31,0,25,40,50,65,80,Simpkins and Hubert (1996) +Rainbow Trout (lentic),NA,0,10,16,20,26,31,0,25,40,50,65,80,Simpkins and Hubert (1996) +Rainbow Trout (lotic),NA,0,10,16,20,26,31,0,25,40,50,65,80,Simpkins and Hubert (1996) Redbreast Sunfish,NA,0,3,5,7,8,10,0,8,13,18,20,25,Bonvechio et al. (2023) Redear Sunfish,NA,0,4,7,9,11,13,0,10,18,23,28,33,Gabelhouse (1984a) River Carpsucker,NA,0,7,11,14,18,22,0,18,28,36,46,56,Bister et al. (2000) @@ -54,14 +74,18 @@ Silver Carp,NA,0,10,17.75,22,29,36.5,0,25,45,56,74,93,Phelps and Willis (2013) Smallmouth Bass,NA,0,7,11,14,17,20,0,18,28,35,43,51,Gabelhouse (1984a) Smallmouth Buffalo ,NA,0,11,18,24,30,37,0,28,46,61,76,94,Bister et al. (2000) Splake,NA,0,8,10,14,16,22,0,20,25,35,40,55,Hyatt (2000) -Spotted Bass,NA,0,7,11,14,17,20,0,18,28,35,43,51,Gabelhouse (1984a) +Spotted Bass,NA,0,5.5,9,12,14,17.25,0,15,23,30,35,44,Sammons et al. (2025) +Spotted Bass (original),NA,0,7,11,14,17,20,0,18,28,35,43,51,Gabelhouse (1984a) Spotted Gar,NA,0,12,19,25,31,39,0,30,48,64,79,99,Bister et al. (2000) Spotted Sunfish,NA,0,2,4,5,6,7,0,5,10,13,15,18,Bonvechio et al. (2023) Striped Bass,landlocked,0,12,20,30,35,45,0,30,51,76,89,114,Gabelhouse (1984a) +Striped Bass (landlocked),NA,0,12,20,30,35,45,0,30,51,76,89,114,Gabelhouse (1984a) Striped Bass X White Bass,NA,0,10,16,20,24,28,0,25,41,51,61,71,Dumont and Neely (2011) Suwannee Bass,NA,0,6,9.75,11.75,13.75,15.75,0,15,25,30,35,40,Bonvechio et al. (2010) Utah Chub,NA,0,4,8,10,12,15,0,10,20,25,30,38,Black et al. (2021) Walleye,NA,0,10,15,20,25,30,0,25,38,51,63,76,Gabelhouse (1984a) +Walleye (overall),NA,0,10,15,20,25,30,0,25,38,51,63,76,Gabelhouse (1984a) +Walleye (30-149 mm),NA,0,6,NA,NA,NA,NA,0,15,NA,NA,NA,NA,Gabelhouse (1984a) Warmouth,NA,0,3,6,8,10,12,0,8,15,20,25,30,Gabelhouse (1984a) White Bass,NA,0,6,9,12,15,18,0,15,23,30,38,46,Gabelhouse (1984a) White Catfish,NA,0,8,13,17,21,26,0,20,33,43,53,66,Bister et al. (2000) diff --git a/data-raw/WSlit.csv b/data-raw/WSlit.csv index 99a58c12..31eb5640 100644 --- a/data-raw/WSlit.csv +++ b/data-raw/WSlit.csv @@ -1,19 +1,27 @@ species,group,measure,units,ref,method,min.len,max.len,int,slope,quad,source,comment Aegean Chub,NA,TL,metric,75,EmP,70,220,-3.801,1.783,0.329,Giannetto et al. (2012),none African Sharptooth Catfish,NA,TL,metric,75,EmP,180,450,-3.668,1.885,0.2087,Emiroglu et al. (2018),only from Sakarya River Basin (Turkey) -Alabama Bass,NA,TL,metric,75,RLP,100,NA,-5.598,3.2904,NA,Dicenzo et al. (1995),min.len not made clear (assumed same as Spotted Bass); same as Spotted Bass (Alabama subspecies) +Alabama Bass,NA,TL,metric,75,EmP,150,550,-5.6189,3.284,NA,Sammons et al. (2025),RLP and EmP (quadratic) models not recommended +Alabama Bass,NA,TL,English,75,EmP,6,22,-3.5339,3.175,NA,Sammons et al. (2025),RLP and EmP (quadratic) models not recommended +Alabama Bass (original),NA,TL,metric,75,RLP,100,NA,-5.598,3.2904,NA,Dicenzo et al. (1995),HAS BEEN REVISED; min.len not made clear (assumed same as Spotted Bass) Ankara Nase,NA,TL,metric,75,EmP,70,240,-10.017,7.402,-0.971,Emiroglu et al. (2020),only from Turkey Arctic Grayling,NA,TL,metric,75,RLP,150,NA,-5.241,3.083,NA,Gilham et al. (2021),authors note that either RLP or EmP method may be used Arctic Grayling,NA,TL,metric,75,EmP,150,NA,-5.279,3.096,NA,Gilham et al. (2021),authors note that either RLP or EmP method may be used Bighead Carp,NA,TL,metric,50,RLP,160,NA,-4.65006,2.88934,NA,Lamer et al. (2019),none Bigmouth Buffalo,NA,TL,English,75,RLP,6,NA,-3.346,3.118,NA,Bister et al. (2000),none Bigmouth Buffalo,NA,TL,metric,75,RLP,150,NA,-5.069,3.118,NA,Bister et al. (2000),none -Bigmouth Sleepers,all,TL,metric,25,EmP,70,390,-6,3.631,-0.111,Cooney and Kwak (2010),none -Bigmouth Sleepers,all,TL,metric,50,EmP,70,390,-5.4,3.153,-0.011,Cooney and Kwak (2010),quadratic term not significant -Bigmouth Sleepers,all,TL,metric,75,EmP,70,390,-4.323,2.237,0.188,Cooney and Kwak (2010),none +Bigmouth Sleepers,overall,TL,metric,25,EmP,70,390,-6,3.631,-0.111,Cooney and Kwak (2010),none +Bigmouth Sleepers,overall,TL,metric,50,EmP,70,390,-5.4,3.153,-0.011,Cooney and Kwak (2010),quadratic term not significant +Bigmouth Sleepers,overall,TL,metric,75,EmP,70,390,-4.323,2.237,0.188,Cooney and Kwak (2010),none Bigmouth Sleepers,lotic,TL,metric,25,EmP,40,390,-6.083,3.708,-0.128,Cooney and Kwak (2010),none Bigmouth Sleepers,lotic,TL,metric,50,EmP,40,390,-5.574,3.302,-0.043,Cooney and Kwak (2010),quadratic term not significant Bigmouth Sleepers,lotic,TL,metric,75,EmP,40,390,-4.933,2.764,0.075,Cooney and Kwak (2010),quadratic term not significant +Bigmouth Sleepers (overall),NA,TL,metric,25,EmP,70,390,-6,3.631,-0.111,Cooney and Kwak (2010),none +Bigmouth Sleepers (overall),NA,TL,metric,50,EmP,70,390,-5.4,3.153,-0.011,Cooney and Kwak (2010),quadratic term not significant +Bigmouth Sleepers (overall),NA,TL,metric,75,EmP,70,390,-4.323,2.237,0.188,Cooney and Kwak (2010),none +Bigmouth Sleepers (lotic),NA,TL,metric,25,EmP,40,390,-6.083,3.708,-0.128,Cooney and Kwak (2010),none +Bigmouth Sleepers (lotic),NA,TL,metric,50,EmP,40,390,-5.574,3.302,-0.043,Cooney and Kwak (2010),quadratic term not significant +Bigmouth Sleepers (lotic),NA,TL,metric,75,EmP,40,390,-4.933,2.764,0.075,Cooney and Kwak (2010),quadratic term not significant Black Bullhead,NA,TL,English,75,RLP,5,NA,-3.297,3.085,NA,Bister et al. (2000),none Black Bullhead,NA,TL,metric,75,RLP,130,NA,-4.974,3.085,NA,Bister et al. (2000),none Black Crappie,NA,TL,English,75,RLP,4,NA,-3.576,3.345,NA,Neumann and Murphy (1991),none @@ -31,12 +39,23 @@ Brook Chub,NA,TL,metric,75,EmP,90,210,-7.75,5.75,-0.66,Giannetto et al. (2012),n Brook Trout,overall,TL,English,75,RLP,4.75,NA,-3.483,3.103,NA,Hyatt and Hubert (2001a),none Brook Trout,overall,TL,metric,75,RLP,120,NA,-5.186,3.103,NA,Hyatt and Hubert (2001a),none Brook Trout,Appalachia,TL,metric,75,EmP,80,226,-3.364,1.378,0.397,Harris et al. (2021),RLP and EmP (linear) models had length-related bias (thus not recommended) +Brook Trout (overall),NA,TL,English,75,RLP,4.75,NA,-3.483,3.103,NA,Hyatt and Hubert (2001a),none +Brook Trout (overall),NA,TL,metric,75,RLP,120,NA,-5.186,3.103,NA,Hyatt and Hubert (2001a),none +Brook Trout (lentic),NA,TL,English,75,RLP,4.75,NA,-3.483,3.103,NA,Hyatt and Hubert (2001a),"Same as Brook Trout, but added lentic/lotic for ease of use with PSDadd" +Brook Trout (lentic),NA,TL,metric,75,RLP,120,NA,-5.186,3.103,NA,Hyatt and Hubert (2001a),"Same as Brook Trout, but added lentic/lotic for ease of use with PSDadd" +Brook Trout (lotic),NA,TL,English,75,RLP,4.75,NA,-3.483,3.103,NA,Hyatt and Hubert (2001a),"Same as Brook Trout, but added lentic/lotic for ease of use with PSDadd" +Brook Trout (lotic),NA,TL,metric,75,RLP,120,NA,-5.186,3.103,NA,Hyatt and Hubert (2001a),"Same as Brook Trout, but added lentic/lotic for ease of use with PSDadd" +Brook Trout (Appalachia),NA,TL,metric,75,EmP,80,226,-3.364,1.378,0.397,Harris et al. (2021),RLP and EmP (linear) models had length-related bias (thus not recommended) Brown Bullhead,NA,TL,English,75,RLP,5,NA,-3.371,3.105,NA,Bister et al. (2000),none Brown Bullhead,NA,TL,metric,75,RLP,130,NA,-5.076,3.105,NA,Bister et al. (2000),none Brown Trout,lentic,TL,English,75,RLP,5.5,NA,-3.592,3.194,NA,Hyatt and Hubert (2001b),none Brown Trout,lentic,TL,metric,75,RLP,140,NA,-5.422,3.194,NA,Hyatt and Hubert (2001b),none Brown Trout,lotic,TL,English,75,RLP,5.5,NA,-3.366,2.96,NA,Milewski and Brown (1994),none Brown Trout,lotic,TL,metric,75,RLP,140,NA,-4.867,2.96,NA,Milewski and Brown (1994),none +Brown Trout (lentic),NA,TL,English,75,RLP,5.5,NA,-3.592,3.194,NA,Hyatt and Hubert (2001b),none +Brown Trout (lentic),NA,TL,metric,75,RLP,140,NA,-5.422,3.194,NA,Hyatt and Hubert (2001b),none +Brown Trout (lotic),NA,TL,English,75,RLP,5.5,NA,-3.366,2.96,NA,Milewski and Brown (1994),none +Brown Trout (lotic),NA,TL,metric,75,RLP,140,NA,-4.867,2.96,NA,Milewski and Brown (1994),none Bull Trout,NA,TL,English,75,RLP,4.75,NA,-3.608,3.115,NA,Hyatt and Hubert (2000),none Bull Trout,NA,TL,metric,75,RLP,120,NA,-5.327,3.115,NA,Hyatt and Hubert (2000),none Burbot,NA,TL,English,75,RLP,8,NA,-3.454,2.898,NA,Fisher et al. (1996),none @@ -48,6 +67,8 @@ Channel Catfish,NA,TL,English,75,RLP,2.75,NA,-3.829,3.294,NA,Brown et al. (1995) Channel Catfish,NA,TL,metric,75,RLP,70,NA,-5.8,3.294,NA,Brown et al. (1995),none Chinook Salmon,NA,TL,English,75,RLP,8,NA,-3.243,2.901,NA,Halseth et al. (1990),none Chinook Salmon,NA,TL,metric,75,RLP,200,NA,-4.661,2.901,NA,Halseth et al. (1990),none +Chinook Salmon (landlocked),NA,TL,English,75,RLP,8,NA,-3.243,2.901,NA,Halseth et al. (1990),Not clear just landlocked; added to simplify use with PSDlit +Chinook Salmon (landlocked),NA,TL,metric,75,RLP,200,NA,-4.661,2.901,NA,Halseth et al. (1990),Not clear just landlocked; added to simplify use with PSDlit Cisco,NA,TL,English,75,RLP,4,NA,-3.644,3.224,NA,Fisher and Fielder (1998),same as for Lake Herring Cisco,NA,TL,metric,75,RLP,100,NA,-5.517,3.224,NA,Fisher and Fielder (1998),same as for Lake Herring Common Carp,NA,TL,English,75,RLP,8,NA,-3.194,2.92,NA,Bister et al. (2000),none @@ -56,12 +77,17 @@ Cutthroat Trout,lentic,TL,English,75,RLP,5,NA,-3.514,3.086,NA,Kruse and Hubert ( Cutthroat Trout,lentic,TL,metric,75,RLP,130,NA,-5.192,3.086,NA,Kruse and Hubert (1997),none Cutthroat Trout,lotic,TL,English,75,RLP,5,NA,-3.492,3.099,NA,Kruse and Hubert (1997),none Cutthroat Trout,lotic,TL,metric,75,RLP,130,NA,-5.189,3.099,NA,Kruse and Hubert (1997),none +Cutthroat Trout (lentic),NA,TL,English,75,RLP,5,NA,-3.514,3.086,NA,Kruse and Hubert (1997),none +Cutthroat Trout (lentic),NA,TL,metric,75,RLP,130,NA,-5.192,3.086,NA,Kruse and Hubert (1997),none +Cutthroat Trout (lotic),NA,TL,English,75,RLP,5,NA,-3.492,3.099,NA,Kruse and Hubert (1997),none +Cutthroat Trout (lotic),NA,TL,metric,75,RLP,130,NA,-5.189,3.099,NA,Kruse and Hubert (1997),none European Chub,NA,TL,metric,75,EmP,70,470,-4.79,2.68,0.1,Giannetto et al. (2011),only from Italy (see Cavedano Chub) European Perch,NA,TL,metric,75,EmP,80,460,-3.1483,1.2663,0.4291,Giannetto et al. (2012),none Flannelmouth Sucker,NA,TL,English,75,RLP,4,NA,-3.527,3.068,NA,Didenko et al. (2004),none Flannelmouth Sucker,NA,TL,metric,75,RLP,100,NA,-5.18,3.068,NA,Didenko et al. (2004),none Flathead Catfish,NA,TL,English,75,RLP,5,NA,-3.661,3.23,NA,Bister et al. (2000),none Flathead Catfish,NA,TL,metric,75,RLP,130,NA,-5.542,3.23,NA,Bister et al. (2000),none +Flier,NA,TL,metric,75,RLP,80,240,-5.013,3.141,NA,Bonvechio et al (2025),none Fourbarbel Scraper,NA,TL,metric,75,EmP,70,280,-6.743,4.768,-0.437,Emiroglu et al. (2020),only from Turkey Freshwater Drum,NA,TL,English,75,RLP,4,NA,-3.575,3.204,NA,Blackwell et al. (1995),none Freshwater Drum,NA,TL,metric,75,RLP,100,NA,-5.419,3.204,NA,Blackwell et al. (1995),none @@ -89,6 +115,8 @@ Largemouth Bass,NA,TL,English,75,RLP,6,NA,-3.587,3.273,NA,Henson (1991),none Largemouth Bass,NA,TL,metric,75,RLP,150,NA,-5.528,3.273,NA,Henson (1991),none Largescale Sucker,NA,TL,English,75,EmP,6.75,25.25,-3.53066,3.12136,NA,Richter (2007),none Largescale Sucker,NA,TL,metric,75,EmP,170,640,-5.2586,3.12136,NA,Richter (2007),none +Longear Sunfish,NA,TL,English,75,RLP,80,180,-3.2887,3.3114,,Miller et al. (2025),none +Longear Sunfish,NA,TL,metric,75,RLP,80,180,5.2861,3.3127,,Miller et al. (2025),none Longnose Gar,NA,TL,English,75,RLP,8,NA,-4.623,3.449,NA,Bister et al. (2000),none Longnose Gar,NA,TL,metric,75,RLP,200,NA,-6.811,3.449,NA,Bister et al. (2000),none Marble Trout,NA,TL,metric,75,EmP,90,570,-5.208,3.202,-0.046,Lorenzoni et al. (2012),none @@ -103,21 +131,32 @@ Muskellunge,male,TL,English,75,RLP,15,NA,-3.921,3.245,NA,Neumann and Willis (199 Muskellunge,male,TL,metric,75,RLP,380,NA,-5.823,3.245,NA,Neumann and Willis (1994),none Muskellunge,overall,TL,English,75,RLP,15,NA,-4.052,3.325,NA,Neumann and Willis (1994),none Muskellunge,overall,TL,metric,75,RLP,380,NA,-6.066,3.325,NA,Neumann and Willis (1994),none +Muskellunge (female),NA,TL,English,75,RLP,15,NA,-4.07,3.34,NA,Neumann and Willis (1994),none +Muskellunge (female),NA,TL,metric,75,RLP,380,NA,-6.105,3.34,NA,Neumann and Willis (1994),none +Muskellunge (male),NA,TL,English,75,RLP,15,NA,-3.921,3.245,NA,Neumann and Willis (1994),none +Muskellunge (male),NA,TL,metric,75,RLP,380,NA,-5.823,3.245,NA,Neumann and Willis (1994),none +Muskellunge (overall),NA,TL,English,75,RLP,15,NA,-4.052,3.325,NA,Neumann and Willis (1994),none +Muskellunge (overall),NA,TL,metric,75,RLP,380,NA,-6.066,3.325,NA,Neumann and Willis (1994),none Nile Tilapia,NA,TL,metric,75,EmP,80,280,-8.7951,6.751,-0.8479,Emiroglu et al. (2018),only from Sakarya River Basin (Turkey) Nipple-Lip Scraper,NA,TL,metric,75,EmP,70,360,-5.966,3.833,-0.181,Emiroglu et al. (2020),only from Turkey Northern Pike,NA,TL,English,75,RLP,4,NA,-3.745,3.096,NA,Anderson and Neumann (1996),none Northern Pike,NA,TL,metric,75,RLP,100,NA,-5.437,3.096,NA,Anderson and Neumann (1996),none -Northern Pikeminnow,NA,FL,English,75,RLP,10,NA,-3.328,2.986,NA,Parker et al. (1995),same as Northern Squawfish -Northern Pikeminnow,NA,FL,metric,75,RLP,250,NA,-4.886,2.986,NA,Parker et al. (1995),same as Northern Squawfish +Northern Pikeminnow,NA,FL,metric,50,EmP,90,580,-5.258,3.135,NA,Voss and Quist (2025),"Other methods and quartiles used, but this was only one that was length-unbiased" +Northern Pikeminnow (original),NA,FL,English,75,RLP,10,NA,-3.328,2.986,NA,Parker et al. (1995),HAS BEEN REVISED; Voss and Quist (2025) note that these equations are problematic and should not be used +Northern Pikeminnow (original),NA,FL,metric,75,RLP,250,NA,-4.886,2.986,NA,Parker et al. (1995),HAS BEEN REVISED; Voss and Quist (2025) note that these equations are problematic and should not be used Northern Snakehead,NA,TL,metric,75,RLP,200,NA,-5.142,3.0418,NA,Kim et al. (2019),from 4 populations -Northern Squawfish,NA,FL,English,75,RLP,10,NA,-3.328,2.986,NA,Parker et al. (1995),same as Northern Pikeminnow -Northern Squawfish,NA,FL,metric,75,RLP,250,NA,-4.886,2.986,NA,Parker et al. (1995),same as Northern Pikeminnow Paddlefish,female,BL,English,75,RLP,11,NA,-2.822,2.782,NA,Brown and Murphy (1993),none Paddlefish,female,BL,metric,75,RLP,280,NA,-4.073,2.782,NA,Brown and Murphy (1993),none Paddlefish,male,BL,English,75,RLP,11,NA,-3.063,2.91,NA,Brown and Murphy (1993),none Paddlefish,male,BL,metric,75,RLP,280,NA,-4.494,2.91,NA,Brown and Murphy (1993),none Paddlefish,overall,BL,English,75,RLP,11,NA,-3.34,3.092,NA,Brown and Murphy (1993),none Paddlefish,overall,BL,metric,75,RLP,280,NA,-5.027,3.092,NA,Brown and Murphy (1993),none +Paddlefish (female),NA,BL,English,75,RLP,11,NA,-2.822,2.782,NA,Brown and Murphy (1993),none +Paddlefish (female),NA,BL,metric,75,RLP,280,NA,-4.073,2.782,NA,Brown and Murphy (1993),none +Paddlefish (male),NA,BL,English,75,RLP,11,NA,-3.063,2.91,NA,Brown and Murphy (1993),none +Paddlefish (male),NA,BL,metric,75,RLP,280,NA,-4.494,2.91,NA,Brown and Murphy (1993),none +Paddlefish (overall),NA,BL,English,75,RLP,11,NA,-3.34,3.092,NA,Brown and Murphy (1993),none +Paddlefish (overall),NA,BL,metric,75,RLP,280,NA,-5.027,3.092,NA,Brown and Murphy (1993),none Palmetto Bass,NA,TL,English,75,RLP,4.5,NA,-3.448,3.139,NA,Brown and Murphy (1991b),same as Striped Bass x White Bass Palmetto Bass,NA,TL,metric,75,RLP,115,NA,-5.201,3.139,NA,Brown and Murphy (1991b),same as Striped Bass x White Bass Pejerrey,NA,TL,English,75,RLP,10,NA,-3.651,3.097,NA,Baigun and Anderson (1993),none @@ -129,6 +168,10 @@ Rainbow Trout,lentic,TL,English,75,RLP,4.75,NA,-3.354,2.99,NA,Simpkins and Huber Rainbow Trout,lentic,TL,metric,75,RLP,120,NA,-4.898,2.99,NA,Simpkins and Hubert (1996),none Rainbow Trout,lotic,TL,English,75,RLP,4.75,NA,-3.432,3.024,NA,Simpkins and Hubert (1996),none Rainbow Trout,lotic,TL,metric,75,RLP,120,NA,-5.023,3.024,NA,Simpkins and Hubert (1996),none +Rainbow Trout (lentic),NA,TL,English,75,RLP,4.75,NA,-3.354,2.99,NA,Simpkins and Hubert (1996),none +Rainbow Trout (lentic),NA,TL,metric,75,RLP,120,NA,-4.898,2.99,NA,Simpkins and Hubert (1996),none +Rainbow Trout (lotic),NA,TL,English,75,RLP,4.75,NA,-3.432,3.024,NA,Simpkins and Hubert (1996),none +Rainbow Trout (lotic),NA,TL,metric,75,RLP,120,NA,-5.023,3.024,NA,Simpkins and Hubert (1996),none Razorback Sucker,NA,TL,English,75,RLP,4.25,NA,-3.35,2.985,NA,Didenko et al. (2004),none Razorback Sucker,NA,TL,metric,75,RLP,110,NA,-4.886,2.985,NA,Didenko et al. (2004),none Redbreast Sunfish,NA,TL,English,75,EmP,3,11.75,-3.2727,3.1215,NA,Bonvechio et al. (2023),also used RLP and EmP-quadratic but did not recommend @@ -166,17 +209,20 @@ Smallmouth Bass,NA,TL,metric,75,RLP,150,NA,-5.329,3.2,NA,Kolander et al. (1993), Smallmouth Buffalo,NA,TL,English,75,RLP,8,NA,-3.448,3.208,NA,Bister et al. (2000),none Smallmouth Buffalo,NA,TL,metric,75,RLP,200,NA,-5.298,3.208,NA,Bister et al. (2000),none South European Roach,NA,TL,metric,75,EmP,60,200,-4.043,1.919,0.315,Giannetto et al. (2016),none -Spotted Bass,overall,TL,English,75,RLP,4,NA,-3.533,3.215,NA,Wiens et al. (1996),none -Spotted Bass,overall,TL,metric,75,RLP,100,NA,-5.392,3.215,NA,Wiens et al. (1996),none -Spotted Bass,Alabama subspecies,TL,metric,75,RLP,100,NA,-5.598,3.2904,NA,Dicenzo et al. (1995),min.len not made clear (assumed same as Spotted Bass); same as Alabama Bass +Spotted Bass,NA,TL,metric,75,EmP,150,490,-5.3467,3.197,NA,Sammons et al. (2025),also used RLP and EmP-quadratic but did not recommend +Spotted Bass,NA,TL,English,75,EmP,6,19.25,-3.3641,3.064,NA,Sammons et al. (2025),also used RLP and EmP-quadratic but did not recommend +Spotted Bass (original),NA,TL,English,75,RLP,4,NA,-3.533,3.215,NA,Wiens et al. (1996),HAS BEEN REVISED +Spotted Bass (original),NA,TL,metric,75,RLP,100,NA,-5.392,3.215,NA,Wiens et al. (1996),HAS BEEN REVISED Spotted Gar,NA,TL,English,75,RLP,10,NA,-4.388,3.431,NA,Bister et al. (2000),none Spotted Gar,NA,TL,metric,75,RLP,250,NA,-6.551,3.431,NA,Bister et al. (2000),none Spotted Sunfish,NA,TL,English,75,EmP,2.75,8,-3.3468,3.3343,NA,Bonvechio et al. (2023),also used RLP and EmP-quadratic but did not recommend Spotted Sunfish,NA,TL,metric,75,EmP,70,200,-5.3739,3.3343,NA,Bonvechio et al. (2023),also used RLP and EmP-quadratic but did not recommend Striped Bass,NA,TL,English,75,RLP,6,NA,-3.358,3.007,NA,Brown and Murphy (1991b),none Striped Bass,NA,TL,metric,75,RLP,150,NA,-4.924,3.007,NA,Brown and Murphy (1991b),none -Striped Bass X White Bass,NA,TL,English,75,RLP,4.5,NA,-3.448,3.139,NA,Brown and Murphy (1991b),same as Palmetto Bass and Striped Bass (Hybrid) -Striped Bass X White Bass,NA,TL,metric,75,RLP,115,NA,-5.201,3.139,NA,Brown and Murphy (1991b),same as Palmetto Bass and Striped Bass (Hybrid) +Striped Bass (landlocked),NA,TL,English,75,RLP,6,NA,-3.358,3.007,NA,Brown and Murphy (1991b),Not clear just landlocked; added to simplify use with PSDlit +Striped Bass (landlocked),NA,TL,metric,75,RLP,150,NA,-4.924,3.007,NA,Brown and Murphy (1991b),Not clear just landlocked; added to simplify use with PSDlit +Striped Bass X White Bass,NA,TL,English,75,RLP,4.5,NA,-3.448,3.139,NA,Brown and Murphy (1991b),same as Palmetto Bass +Striped Bass X White Bass,NA,TL,metric,75,RLP,115,NA,-5.201,3.139,NA,Brown and Murphy (1991b),same as Palmetto Bass Suwannee Bass,NA,TL,metric,75,EmP,110,NA,-0.106,-1.363,0.995,Bonvechio et al. (2010),none Tiger Muskellunge,NA,TL,English,75,RLP,9.5,NA,-4.095,3.337,NA,Rogers and Koupal (1997),none Tiger Muskellunge,NA,TL,metric,75,RLP,240,NA,-6.126,3.337,NA,Rogers and Koupal (1997),none @@ -186,6 +232,10 @@ Walleye,overall,TL,English,75,RLP,6,NA,-3.642,3.18,NA,Murphy et al. (1990),none Walleye,overall,TL,metric,75,RLP,150,NA,-5.453,3.18,NA,Murphy et al. (1990),none Walleye,30-149 mm,TL,English,75,RLP,1.25,6,-3.431,2.869,NA,Flammang et al. (1999),none Walleye,30-149 mm,TL,metric,75,RLP,30,149,-4.804,2.869,NA,Flammang et al. (1999),none +Walleye (overall),NA,TL,English,75,RLP,6,NA,-3.642,3.18,NA,Murphy et al. (1990),none +Walleye (overall),NA,TL,metric,75,RLP,150,NA,-5.453,3.18,NA,Murphy et al. (1990),none +Walleye (30-149 mm),NA,TL,English,75,RLP,1.25,6,-3.431,2.869,NA,Flammang et al. (1999),none +Walleye (30-149 mm),NA,TL,metric,75,RLP,30,149,-4.804,2.869,NA,Flammang et al. (1999),none Warmouth,NA,TL,English,75,RLP,3,NA,-3.284,3.241,NA,Bister et al. (2000),none Warmouth,NA,TL,metric,75,RLP,80,NA,-5.18,3.241,NA,Bister et al. (2000),none White Bass,NA,TL,English,75,RLP,4.5,NA,-3.394,3.081,NA,Brown and Murphy (1991b),none diff --git a/data-raw/aaa_Make_Fake_PSDWR_Data.R b/data-raw/aaa_Make_Fake_PSDWR_Data.R new file mode 100644 index 00000000..d31ce5da --- /dev/null +++ b/data-raw/aaa_Make_Fake_PSDWR_Data.R @@ -0,0 +1,136 @@ +## Creates weight-length data for a variety of species (some with sub-groups) to +## be used as examples in PSD and Wr calculations. Running the script will produce +## a data.frame called PSDWRtest that is distributed with FSA. +set.seed(633437) + +bgdf <- data.frame(species="Bluegill Sunfish", + location="Bass Lake", + len=round(c(rnorm(30,mean=100,sd=15), + rnorm(70,mean=150,sd=25), + rnorm(20,mean=200,sd=25)),0)) |> + dplyr::mutate(wt=10^(-5.37)*len^3.316, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=NA_character_) + +bktdf <- data.frame(species="Brook Trout", + location="Trout Lake", + len=round(c(rnorm(20,mean=175,sd=25), + rnorm(50,mean=255,sd=25), + rnorm(10,mean=310,sd=25)),0)) |> + dplyr::mutate(wt=10^(-5.18)*len^3.1, + wt=round(wt+rnorm(dplyr::n(),wt*0.10),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M"),dplyr::n(),replace=TRUE), + sex=NA_character_) + +brt1df <- data.frame(species="Brown Trout", + location="Trout Lake", + len=round(c(rnorm(20,mean=150,sd=20), + rnorm(50,mean=230,sd=25), + rnorm(10,mean=325,sd=25)),0)) |> + dplyr::mutate(wt=1.4e-05*len^2.96, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M"),dplyr::n(),replace=TRUE), + sex=NA_character_) + +brt2df <- data.frame(species="Brown Trout", + location="Brushy Creek", + len=round(c(rnorm(24,mean=200,sd=20), + rnorm(60,mean=325,sd=25), + rnorm(15,mean=450,sd=25)),0)) |> + dplyr::mutate(wt=3.65e-06*len^3.1, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M"),dplyr::n(),replace=TRUE)) + +iaddf <- FSAdata::InchLake2 |> + dplyr::filter(species=="Iowa Darter") |> + dplyr::mutate(species=="Iowa Darter", + location="Bass Lake", + sex=NA_character_, + len=round(length*25.4,0), + wt=NA) |> + dplyr::select(species,location,len,wt=weight,sex) + +lmbdf <- data.frame(species="Largemouth Bass", + location="Bass Lake", + len=round(c(rnorm(30,mean=200,sd=15), + rnorm(40,mean=300,sd=25), + rnorm(20,mean=350,sd=25)),0)) |> + dplyr::mutate(wt=10^(-5.5)*len^3.2, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=NA_character_) + +lktdf <- data.frame(species="Lean Lake Trout", + location="Trout Lake", + len=round(c(rnorm(10,mean=300,sd=40), + rnorm(60,mean=500,sd=50), + rnorm(30,mean=750,sd=50)),0)) |> + dplyr::mutate(wt=10^(-5.7)*len^3.246, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M"),dplyr::n(),replace=TRUE)) + +muedf <- data.frame(species="Muskellunge", + location="Long Lake", + len=round(c(rnorm(10,mean=600,sd=60), + rnorm(25,mean=800,sd=70), + rnorm(10,mean=1000,sd=60)),0)) |> + dplyr::mutate(wt=10^(-6.0)*len^3.32, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M","U"),dplyr::n(),c(0.4,0.4,0.2),replace=TRUE)) + +rufdf <- data.frame(species="Ruffe", + location="Round Lake", + len=round(c(rnorm(10,mean=70,sd=40), + rnorm(20,mean=120,sd=20), + rnorm(10,mean=160,sd=20)),0)) |> + dplyr::mutate(wt=3.03e-06*len^3.26, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=NA_character_) + +waedf1 <- data.frame(species="Walleye", + location="Bass Lake", + len=round(rnorm(50,mean=100,sd=25),0)) |> + dplyr::filter(len<150) |> + dplyr::mutate(wt=10^(-4.8)*len^2.87, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.05),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=NA_character_) + +waedf2 <- data.frame(species="Walleye", + location="Bass Lake", + len=round(c(rnorm(20,mean=250,sd=25), + rnorm(60,mean=425,sd=40), + rnorm(30,mean=600,sd=40)),0)) |> + dplyr::filter(len>=150) |> + dplyr::mutate(wt=10^(-5.45)*len^3.18, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.1),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M"),dplyr::n(),replace=TRUE), + sex=ifelse(len<300,NA,sex)) + +yepdf <- data.frame(species="Yellow Perch", + location="Bass Lake", + len=round(c(rnorm(100,mean=150,sd=25), + rnorm(50,mean=250,sd=25), + rnorm(20,mean=300,sd=25)),0)) |> + dplyr::mutate(wt=10^(-5.38)*len^3.23, + wt=round(wt+rnorm(dplyr::n(),0,wt*0.10),1), + wt=ifelse(wt<=0,min(wt[wt>0]),wt), + sex=sample(c("F","M"),dplyr::n(),replace=TRUE), + sex=ifelse(len<100,NA,sex)) + +## Combine +PSDWRtest <- rbind(bgdf,bktdf,brt1df,brt2df,iaddf,lmbdf,lktdf,muedf,rufdf,waedf1,waedf2,yepdf) + +## Add some (~5%) random NAs to wt +PSDWRtest$wt[sample(nrow(PSDWRtest),round(0.05*nrow(PSDWRtest),0))] <- NA_real_ + +## Write out to Rdata file +usethis::use_data(PSDWRtest,internal=FALSE,overwrite=TRUE) diff --git a/data/PSDWRtest.rda b/data/PSDWRtest.rda new file mode 100644 index 00000000..88275b78 Binary files /dev/null and b/data/PSDWRtest.rda differ diff --git a/data/PSDlit.rdata b/data/PSDlit.rdata index 2f3712b5..4ffaa7a2 100644 Binary files a/data/PSDlit.rdata and b/data/PSDlit.rdata differ diff --git a/data/WSlit.rdata b/data/WSlit.rdata index 5794798e..733a0e2e 100644 Binary files a/data/WSlit.rdata and b/data/WSlit.rdata differ diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index dac18f7d..907da808 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -7,7 +7,7 @@ FSA - 0.10.0 + 0.10.1 "; + if (ClipboardJS.isSupported()) { + $(document).ready(function () { + var copyButton = ""; - $("div.sourceCode").addClass("hasCopyButton"); + $("div.sourceCode").addClass("hasCopyButton"); - // Insert copy buttons: - $(copyButton).prependTo(".hasCopyButton"); + // Insert copy buttons: + $(copyButton).prependTo(".hasCopyButton"); - // Initialize tooltips: - $('.btn-copy-ex').tooltip({container: 'body'}); + // Initialize tooltips: + $('.btn-copy-ex').tooltip({ container: 'body' }); - // Initialize clipboard: - var clipboard = new ClipboardJS('[data-clipboard-copy]', { - text: function(trigger) { - return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); - } - }); + // Initialize clipboard: + var clipboard = new ClipboardJS('[data-clipboard-copy]', { + text: function (trigger) { + return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); + } + }); - clipboard.on('success', function(e) { - changeTooltipMessage(e.trigger, 'Copied!'); - e.clearSelection(); - }); + clipboard.on('success', function (e) { + changeTooltipMessage(e.trigger, 'Copied!'); + e.clearSelection(); + }); - clipboard.on('error', function(e) { - changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); - }); + clipboard.on('error', function (e) { + changeTooltipMessage(e.trigger, 'Press Ctrl+C or Command+C to copy'); + }); - }); - } + }); + } /* Search marking --------------------------*/ var url = new URL(window.location.href); @@ -80,80 +80,80 @@ }); } - /* Search --------------------------*/ - /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ + /* Search --------------------------*/ + /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ // Initialise search index on focus - var fuse; - $("#search-input").focus(async function(e) { - if (fuse) { - return; - } - - $(e.target).addClass("loading"); - var response = await fetch($("#search-input").data("search-index")); - var data = await response.json(); + var fuse; + $("#search-input").focus(async function (e) { + if (fuse) { + return; + } + + $(e.target).addClass("loading"); + var response = await fetch($("#search-input").data("search-index")); + var data = await response.json(); + + var options = { + keys: ["what", "text", "code"], + ignoreLocation: true, + threshold: 0.1, + includeMatches: true, + includeScore: true, + }; + fuse = new Fuse(data, options); + + $(e.target).removeClass("loading"); + }); + // Use algolia autocomplete var options = { - keys: ["what", "text", "code"], - ignoreLocation: true, - threshold: 0.1, - includeMatches: true, - includeScore: true, + autoselect: true, + debug: true, + hint: false, + minLength: 2, }; - fuse = new Fuse(data, options); - - $(e.target).removeClass("loading"); - }); - - // Use algolia autocomplete - var options = { - autoselect: true, - debug: true, - hint: false, - minLength: 2, - }; - var q; -async function searchFuse(query, callback) { - await fuse; - - var items; - if (!fuse) { - items = []; - } else { - q = query; - var results = fuse.search(query, { limit: 20 }); - items = results - .filter((x) => x.score <= 0.75) - .map((x) => x.item); - if (items.length === 0) { - items = [{dir:"Sorry 😿",previous_headings:"",title:"No results found.",what:"No results found.",path:window.location.href}]; + var q; + async function searchFuse(query, callback) { + await fuse; + + var items; + if (!fuse) { + items = []; + } else { + q = query; + var results = fuse.search(query, { limit: 20 }); + items = results + .filter((x) => x.score <= 0.75) + .map((x) => x.item); + if (items.length === 0) { + items = [{ dir: "Sorry 😿", previous_headings: "", title: "No results found.", what: "No results found.", path: window.location.href }]; + } + } + callback(items); } - } - callback(items); -} - $("#search-input").autocomplete(options, [ - { - name: "content", - source: searchFuse, - templates: { - suggestion: (s) => { - if (s.title == s.what) { - return `${s.dir} >
${s.title}
`; - } else if (s.previous_headings == "") { - return `${s.dir} >
${s.title}
> ${s.what}`; - } else { - return `${s.dir} >
${s.title}
> ${s.previous_headings} > ${s.what}`; - } + $("#search-input").autocomplete(options, [ + { + name: "content", + source: searchFuse, + templates: { + suggestion: (s) => { + if (s.title == s.what) { + return `${s.dir} >
${s.title}
`; + } else if (s.previous_headings == "") { + return `${s.dir} >
${s.title}
> ${s.what}`; + } else { + return `${s.dir} >
${s.title}
> ${s.previous_headings} > ${s.what}`; + } + }, }, }, - }, - ]).on('autocomplete:selected', function(event, s) { - window.location.href = s.path + "?q=" + q + "#" + s.id; - }); + ]).on('autocomplete:selected', function (event, s) { + window.location.href = s.path + "?q=" + q + "#" + s.id; + }); }); })(window.jQuery || window.$) -document.addEventListener('keydown', function(event) { +document.addEventListener('keydown', function (event) { // Check if the pressed key is '/' if (event.key === '/') { event.preventDefault(); // Prevent any default action associated with the '/' key diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index 3b5d1c0a..7354fde7 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -1,13 +1,14 @@ -pandoc: '3.2' -pkgdown: 2.1.2 +pandoc: 3.6.3 +pkgdown: 2.2.0 pkgdown_sha: ~ articles: articles/Computing_PSDs: Computing_PSDs.html + articles/Computing_PSDs_and_RelativeWeights: Computing_PSDs_and_RelativeWeights.html articles/Computing_Relative_Weights: Computing_Relative_Weights.html articles/Fitting_Growth_Functions: Fitting_Growth_Functions.html articles/Growth_Function_Parameterizations: Growth_Function_Parameterizations.html articles/Growth_Starting_Values: Growth_Starting_Values.html -last_built: 2025-05-06T17:31Z +last_built: 2026-01-08T20:22Z urls: reference: https://fishr-core-team.github.io/FSA/reference article: https://fishr-core-team.github.io/FSA/articles diff --git a/docs/reference/BluegillJL.html b/docs/reference/BluegillJL.html index 01c79a34..739920a4 100644 --- a/docs/reference/BluegillJL.html +++ b/docs/reference/BluegillJL.html @@ -7,7 +7,7 @@ FSA - 0.10.0 + 0.10.1