From b204966a524ef998e7e79acc88c497dac769d514 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Tue, 6 May 2025 16:54:25 -0500 Subject: [PATCH 01/16] Starting v0.10.9000 --- DESCRIPTION | 2 +- NEWS.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 01f54531..f391fcfe 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: FSA -Version: 0.10.0 +Version: 0.10.9000 Date: 2025-5-6 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. diff --git a/NEWS.md b/NEWS.md index 446706ae..35efa17d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +# FSA 0.10.9000 + + # 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()`). From ab39080f868ec9eb42d933f6b100aa49db2cd0b1 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Sat, 9 Aug 2025 09:32:02 -0500 Subject: [PATCH 02/16] Added Flier and Longear Sunfish Ws values --- DESCRIPTION | 2 +- NEWS.md | 2 +- data-raw/PSDlit.csv | 1 + data-raw/WSlit.csv | 3 +++ data/PSDlit.rdata | Bin 2426 -> 2456 bytes data/WSlit.rdata | Bin 5399 -> 5479 bytes 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f391fcfe..7187dba5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-5-6 +Date: 2025-8-8 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/NEWS.md b/NEWS.md index 35efa17d..68e26015 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,5 @@ # FSA 0.10.9000 - +* `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#100](https://github.com/fishR-Core-Team/FSA/issues/122)). # 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). diff --git a/data-raw/PSDlit.csv b/data-raw/PSDlit.csv index 473af9fd..79c9ee7a 100644 --- a/data-raw/PSDlit.csv +++ b/data-raw/PSDlit.csv @@ -21,6 +21,7 @@ Chinook Salmon,landlocked,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) 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) diff --git a/data-raw/WSlit.csv b/data-raw/WSlit.csv index 99a58c12..7ff65ce0 100644 --- a/data-raw/WSlit.csv +++ b/data-raw/WSlit.csv @@ -62,6 +62,7 @@ Flannelmouth Sucker,NA,TL,English,75,RLP,4,NA,-3.527,3.068,NA,Didenko et al. (20 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 +90,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 diff --git a/data/PSDlit.rdata b/data/PSDlit.rdata index 2f3712b512d345ad90865671b442b0573b290969..2c3389246a1c7dba9e425c9d096c6dc27e1129d2 100644 GIT binary patch literal 2456 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 WtatC;{aK2Cs_`#KU%?OeCjbD9h$XE6 literal 2426 zcmV-=35E6_iwFP!000002JKqgRvXC`?U}JLSBt?Uz{DY)G0TH*MBF^!8OB0jL;|)k zvImoywK9cNpk8WqD}6DGd5L}_dCXVj(I1ffL!R=SFNjm6KD*U*xR^k052Ll3)3vM4 zZJ$%st%bH%U(fcw?zJrIBkRhQ53P@`s$1*otCwpJ7A#8vmi2*k#p+SAYpcBKI+0p= zLydCk8dTRh&E}SaO5{}RQXr08$2%anzvvv)q^Q~}B4`pesIZ0~M>V?`@9zuOC;WQR z6_vUIU016R+MA#m{Q*J((QG<0b>zlUt%~-Yutr$7#tt0UrEy;|@cp{|GEmO{CFr_> z4m}=OUxIR72K8z!1L-Qp!JePmUa1Mkv$vc|T?P`N<`n9A(q$Q`#g3<=D+{;bd+@sA zH`FN0QEnxUqFUgK$Z$Ql=8A~wk+qv!3uIV36p;+<)gW$w)ROc4_adm;wZTjAU=ZDfR2`KkHjl;Th-Pk*Tn}KJ3peP75<#m8VDOmQDyKMVyiE7oAS+2H( z>pF^)C{|&lMHoy8&n2`>ZNst5M`LnF_Rw`FxNkRps2ao5#^ z6ahmAx1Bete42HGz@BYi@2ZaftJ`YZA@i=Xh!4`W*V>~_AI<)$A+vTBeAtW)G1Ad`>&auhgCQ+q6n z*{|)LniEN*VCDEwZ#)C+c@>FTyE8%4j!K|IQ}>Pt+UbC{<7N}Y+;jkqbF41`w`5RB z6G@T_X9Jou{OB0XQbT&&D@T@ryioe1j~0;CYgB z%+ENRzsur?sT@N6@QdDzR7oMICA3>%}a@C$q36}G;Rx6PU)w!_*N4&*?8Go^5+5?V!a1NqAh!eb^e&7>v zqb~fMMnA$2;=gaMvwrwKa^8=5ZlezDIh*$RUAE39ImhH(Ci%I|*Yk6mOa5HJc!tfN z79W4_2QE4V~H2-tLhH0$V=?dMZ>kjE_d5d)QI(?dqk={eH zr^iF;nxQrN$-Aj8{RGl)Df$F|Ot!{JXOiL_BAZ(F(EP28p9ge5MPq%RS645^bSD$f zZL&SW@GzL#P2ED76$nURd?Ix|8Y^gu3gxj06ew^~0C;v-y%~Px;9S7;?JU$^G z;8{P_mnqh7)FntqSMeoXvot?UzJ@5L36lLZKSe%tt_yU(L{eV`%5^hSzcIQ;JogA2 zBReB>jb(V!G3=6^&(!sXba!dpOopckT7R4J)Nk{TDMziZdqMA@uXP-x^MHKA-X!t8 zMX?6zs*{f1r8T;iXnu@*4O^XF(egUYFHoMkSAIqJo8(8|Kev*;+0F1bPH~S>F7t$q zlbxG%jaxXs@xJiQ+eGfrxRfMW*rPGN-+W7BoDH4wb~7bZdSb zN_%p8abZrJ*Xrq-7nwOJuiUa%l|krx?X~ZN&&qNnv942DkN0GdIGV=v*i*-qhhg1m zuSou}tZXmNofX~iniJMC{?z)1mto*X>x$%d0ITu-{!!cDImjN_2sD^YO(}k!M*bpp zyd<0H_Z$0ZO0Bk6ilacrnp3@M_DnJqgRVjT%cVYij|JE&osqh z;v!R=x%d0K*hV>h=Hm^gkuf&Cm=-PRF`dBEIB3>bwTH{KxFNi39BFHfti}!BOM3a4 zljXUI33QT2^M_qmJ<*UM zJ<@adA9mQ36-TDO895027{BZ23*)^o@+=?qYl#F4CKBH0$I&q z4cYJmvFFMT))NK3I(s@m$6KXgdP~Qtw-m{E>tG#kDF$yT&=vY|P?4OXimQKUkx&G% sw<;nrwI3+<*zz8AkWPVB{l(-%{TlV|-Mc?2@eh6d6Fy2P+ju7c0NVuo$^ZZW diff --git a/data/WSlit.rdata b/data/WSlit.rdata index 5794798e30775b8f92e23a0902dbfc063a644cbe..e6120c2156230232798dca408b2d31eba17fe236 100644 GIT binary patch literal 5479 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 Date: Sat, 9 Aug 2025 11:47:49 -0500 Subject: [PATCH 03/16] Added PSD for Longear Sunfish --- NEWS.md | 1 + data-raw/PSDlit.csv | 1 + data/PSDlit.rdata | Bin 2456 -> 2480 bytes 3 files changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 68e26015..6fcd06e3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,5 @@ # FSA 0.10.9000 +* `PSDlit`: Added info for Flier and Longear Sunfish. * `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#100](https://github.com/fishR-Core-Team/FSA/issues/122)). # FSA 0.10.0 diff --git a/data-raw/PSDlit.csv b/data-raw/PSDlit.csv index 79c9ee7a..d6fe7abd 100644 --- a/data-raw/PSDlit.csv +++ b/data-raw/PSDlit.csv @@ -32,6 +32,7 @@ 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) Northern Pike,NA,0,14,21,28,34,44,0,35,53,71,86,112,Gabelhouse (1984a) diff --git a/data/PSDlit.rdata b/data/PSDlit.rdata index 2c3389246a1c7dba9e425c9d096c6dc27e1129d2..0d121fa4add3d8b68e21900912efceed6b85117e 100644 GIT binary patch literal 2480 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 literal 2456 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 WtatC;{aK2Cs_`#KU%?OeCjbD9h$XE6 From b0ad4afd7d86f77f689e535a4be0cdd7efba4ee3 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Sat, 9 Aug 2025 13:07:49 -0500 Subject: [PATCH 04/16] Added some error checking to chapmanRobson (closes #131 ) --- NEWS.md | 3 ++- R/chapmanRobson.R | 10 ++++++++++ tests/testthat/testthat_catchCurve.R | 12 ++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 6fcd06e3..9d60ec92 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # FSA 0.10.9000 +* `chapmanRobson()`: Added catch for when n+T<1 and n+T<2. This addresses [#131](https://github.com/fishR-Core-Team/FSA/issues/131)). * `PSDlit`: Added info for Flier and Longear Sunfish. -* `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#100](https://github.com/fishR-Core-Team/FSA/issues/122)). +* `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). # 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). 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/tests/testthat/testthat_catchCurve.R b/tests/testthat/testthat_catchCurve.R index eb1e958b..616d9c1f 100644 --- a/tests/testthat/testthat_catchCurve.R +++ b/tests/testthat/testthat_catchCurve.R @@ -9,6 +9,12 @@ cr <- chapmanRobson(catch~age,data=d,ages2use=2:6) cr1 <- chapmanRobson(catch~age,data=d,ages2use=2:6,zmethod="Hoenigetal") cr2 <- chapmanRobson(catch~age,data=d,ages2use=2:6,zmethod="original") +# for testing too small CPE in catch in chapmanRobson() +d2 <- data.frame(age=7:13, + cpe=c(0.089,0.070,0.055,0.024,0.018,0.023,0.028), + cpex2=c(0.178,0.140,0.110,0.048,0.036,0.046,0.056), + cpex10=c(0.89,0.70,0.55,0.24,0.18,0.23,0.28)) + ## Test Messages ---- test_that("catchCurve() messages",{ @@ -133,6 +139,12 @@ test_that("chapmanRobson errors and warnings",{ # bad args in confint expect_error(plot(cr,ylim=c(3,7,10)), "may not have more than two") + # too small CPE in catch + expect_error(chapmanRobson(cpe~age,data=d2), + "The sum of") + expect_error(chapmanRobson(cpex2~age,data=d2), + "The sum of") + expect_no_error(chapmanRobson(cpex10~age,data=d2)) }) From 9d2b108ce7d8ee5b796bb1fd306e6109ce8b6329 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Tue, 19 Aug 2025 08:18:08 -0500 Subject: [PATCH 05/16] Changes to metaM() to address #133 --- DESCRIPTION | 2 +- NEWS.md | 1 + R/metaM.R | 22 +++++++++++++++------- man/metaM.Rd | 13 ++++++++----- tests/testthat/testthat_metaM.R | 7 ++++--- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7187dba5..1507a707 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-8-8 +Date: 2025-8-16 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/NEWS.md b/NEWS.md index 9d60ec92..e2c813e1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # FSA 0.10.9000 * `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. * `PSDlit`: Added info for Flier and Longear Sunfish. * `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). 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/man/metaM.Rd b/man/metaM.Rd index 4361c863..9104d3d3 100644 --- a/man/metaM.Rd +++ b/man/metaM.Rd @@ -74,6 +74,7 @@ One of several methods is chosen with \code{method}. The available methods can b \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}. @@ -92,9 +93,9 @@ One of several methods is chosen with \code{method}. The available methods can b Conditional mortality (cm) is estimated from instantaneous natural mortality (M) with 1-exp(-M). It is returned with M here simply as a courtesy for those using the \code{rFAMS} package. } \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}. + 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. } \section{IFAR Chapter}{ @@ -107,7 +108,7 @@ Mmethods() Mmethods("tmax") ## Simple Examples -metaM("tmax",tmax=20) +metaM("HamelCope",tmax=20) metaM("HoenigNLS",tmax=20) metaM("HoenigNLS",tmax=20,verbose=FALSE) @@ -132,7 +133,7 @@ metaM(c("RikhterEfanov1","PaulyL","HoenigO","HewittHoenig","AlversonCarney"), ## 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) @@ -155,6 +156,8 @@ Charnov, E.L., H. Gislason, and J.G. Pope. 2013. Evolutionary assembly rules for 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.] @@ -180,7 +183,7 @@ Then, A.Y., J.M. Hoenig, N.G. Hall, and D.A. Hewitt. 2015. Evaluating the predic Zhang, C-I and B.A. Megrey. 2006. A revised Alverson and Carney model for estimating the instantaneous rate of natural mortality. Transactions of the American Fisheries Society. 135-620-633. [Was (is?) from http://www.pmel.noaa.gov/foci/publications/2006/zhan0531.pdf.] } \seealso{ -See \code{\link[fishmethods]{M.empirical}} in \pkg{fishmethods} for similar functionality. +See \code{\link[fishmethods]{M.empirical}} in \pkg{fishmethods} for similar functionality and the "Natural Mortality Tool" Shiny app on-line. } \author{ Derek H. Ogle, \email{DerekOgle51@gmail.com} diff --git a/tests/testthat/testthat_metaM.R b/tests/testthat/testthat_metaM.R index 20dd4e24..76b802b4 100644 --- a/tests/testthat/testthat_metaM.R +++ b/tests/testthat/testthat_metaM.R @@ -10,8 +10,8 @@ test_that("metaM() messages",{ "should be one of") ## missing parameters - # default tmax method - expect_error(metaM("tmax"), + # default tmax1 method + expect_error(metaM("tmax1"), "must be given to") # Pauly L method expect_error(metaM("PaulyL",Linf=200,K=0.3), @@ -136,7 +136,8 @@ test_that("metaM() matches results from Kenchington (2014)",{ expect_equal(round(tmp$M,2)[-7],tmp$expM[-7]) ## Norwegian Fjord Lanternfish - ## matches except for the HoenigOF and HoenigO2F, which Kenchington acknowledged as erroneous + ## matches except for the HoenigOF and HoenigO2F, which Kenchington + ## acknowledged as erroneous tmp <- metaM(meths,tmax=8,Linf=8.306,Winf=8.68,K=0.204,t0=-0.64, b=3.26,t50=2,T=8,L=2) tmp <- data.frame(tmp,expM=c(0.51,0.46,0.55,0.61,0.58,0.64,0.31, From fd26df12b1412e4eb5411e90ed42bfd56e636003 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Thu, 25 Sep 2025 21:00:48 -0500 Subject: [PATCH 06/16] Fixing muliple groups error in psdAdd --- DESCRIPTION | 2 +- NEWS.md | 1 + R/psdAdd.R | 28 +++++++++++++++++----------- man/psdAdd.Rd | 16 +++++++++++----- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 1507a707..c875fd8d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-8-16 +Date: 2025-9-26 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/NEWS.md b/NEWS.md index e2c813e1..08b51a41 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # FSA 0.10.9000 * `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 but as described in [#136](https://github.com/fishR-Core-Team/FSA/issues/136)). Thanks to Dave Glover. * `PSDlit`: Added info for Flier and Longear Sunfish. * `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). diff --git a/R/psdAdd.R b/R/psdAdd.R index 569d69e9..b5fcff7c 100644 --- a/R/psdAdd.R +++ b/R/psdAdd.R @@ -90,15 +90,21 @@ #' "Largemouth Bass"=c(254,356))) #' peek(df,n=20) #' -#' #===== Example for a species with sub-groups +#' #===== Example for some 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) +#' dcs <- data.frame(species=factor(rep(c("Chinook Salmon"),20)), +#' tl=round(rnorm(20,450,50),0)) +#' df2 <- rbind(dbt,dlt,dcs) #' -#' df2$psd <- psdAdd(tl~species,data=df2,group=list("Brown Trout"="lentic")) -#' peek(df2,n=6) +#' df2$psd <- psdAdd(tl~species,data=df2, +#' group=list("Brown Trout"="lentic", +#' "Chinook Salmon"="landlocked"), +#' addLens=list("Brown Trout"=240, +#' "Lake Trout"=425)) +#' peek(df2,n=20) #' #' @rdname psdAdd #' @export @@ -120,8 +126,8 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), ## Prepare the PSD literature values data frame PSDlit <- FSA::PSDlit ## 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 @@ -138,7 +144,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 +156,10 @@ 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) # 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]) diff --git a/man/psdAdd.Rd b/man/psdAdd.Rd index 4026a71e..24032353 100644 --- a/man/psdAdd.Rd +++ b/man/psdAdd.Rd @@ -123,15 +123,21 @@ df$psd4 <- psdAdd(tl~species,data=df,verbose=FALSE, "Largemouth Bass"=c(254,356))) peek(df,n=20) -#===== Example for a species with sub-groups +#===== Example for some 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) +dcs <- data.frame(species=factor(rep(c("Chinook Salmon"),20)), + tl=round(rnorm(20,450,50),0)) +df2 <- rbind(dbt,dlt,dcs) + +df2$psd <- psdAdd(tl~species,data=df2, + group=list("Brown Trout"="lentic", + "Chinook Salmon"="landlocked"), + addLens=list("Brown Trout"=240, + "Lake Trout"=425)) +peek(df2,n=20) } \references{ From df7994922f51030f9c1870c8cc27a258f849fc15 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Sun, 28 Sep 2025 15:35:19 -0500 Subject: [PATCH 07/16] Changes to wrAdd for #136 --- DESCRIPTION | 2 +- NEWS.md | 3 ++- R/wrAdd.R | 27 ++++++++++++++++++++++----- man/wrAdd.Rd | 17 +++++++++++++++++ tests/testthat/testthat_WSWR.R | 18 ++++++++++++++++++ 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c875fd8d..036751d4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-9-26 +Date: 2025-10-1 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/NEWS.md b/NEWS.md index 08b51a41..8b49bf04 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,9 @@ # FSA 0.10.9000 * `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 but as described in [#136](https://github.com/fishR-Core-Team/FSA/issues/136)). Thanks to Dave Glover. +* `psdAdd()`: Addressed bug as described in [#136](https://github.com/fishR-Core-Team/FSA/issues/136)). Thanks to Dave Glover. * `PSDlit`: Added info for Flier and Longear Sunfish. +* `wrAdd()`: Addressed bug similar to that for `psdAdd()`. * `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). # FSA 0.10.0 diff --git a/R/wrAdd.R b/R/wrAdd.R index 22265c49..e5b45d62 100644 --- a/R/wrAdd.R +++ b/R/wrAdd.R @@ -77,6 +77,23 @@ #' WsOpts=list(Walleye=list(group="overall"))) #' peek(wae,n=10) #' +#' #===== Example with a species that has Ws eqns for multiple reference values +#' # and one must be specified with WsOpts +#' ruf <- data.frame(species=factor(rep(c("Ruffe"),30)), +#' tl=round(rnorm(30,130,20),0)) +#' ruf$wt <- round(3.03e-06*ruf$tl^3.26+rnorm(30,0,10),1) +#' # ruf$Wr <- wrAdd(wt~tl+species,data=ruf) # will err b/c multiple refs +#' ruf$Wr <- wrAdd(wt~tl+species,data=ruf, +#' WsOpts=list(Ruffe=list(ref=75))) +#' peek(ruf,n=10) +#' +#' #===== Example with two uses of WsOpts (and one species without) +#' df2 <- rbind(wae[-4],dbg,ruf[-4]) +#' df2$Wr1 <- wrAdd(wt~tl+species,data=df2, +#' WsOpts=list(Walleye=list(group="overall"), +#' Ruffe=list(ref=75))) +#' peek(df2,n=15) +#' #' @rdname wrAdd #' @export wrAdd <- function (wt,...) { @@ -107,7 +124,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 +143,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 @@ -166,8 +183,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)) { diff --git a/man/wrAdd.Rd b/man/wrAdd.Rd index 1eb0dbba..ef62bea5 100644 --- a/man/wrAdd.Rd +++ b/man/wrAdd.Rd @@ -93,6 +93,23 @@ wae$Wr <- wrAdd(wt~tl+species,data=wae, WsOpts=list(Walleye=list(group="overall"))) peek(wae,n=10) +#===== Example with a species that has Ws eqns for multiple reference values +# and one must be specified with WsOpts +ruf <- data.frame(species=factor(rep(c("Ruffe"),30)), + tl=round(rnorm(30,130,20),0)) +ruf$wt <- round(3.03e-06*ruf$tl^3.26+rnorm(30,0,10),1) +# ruf$Wr <- wrAdd(wt~tl+species,data=ruf) # will err b/c multiple refs +ruf$Wr <- wrAdd(wt~tl+species,data=ruf, + WsOpts=list(Ruffe=list(ref=75))) +peek(ruf,n=10) + +#===== Example with two uses of WsOpts (and one species without) +df2 <- rbind(wae[-4],dbg,ruf[-4]) +df2$Wr1 <- wrAdd(wt~tl+species,data=df2, + WsOpts=list(Walleye=list(group="overall"), + Ruffe=list(ref=75))) +peek(df2,n=15) + } \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. diff --git a/tests/testthat/testthat_WSWR.R b/tests/testthat/testthat_WSWR.R index f5a758dc..9bd4e8d8 100644 --- a/tests/testthat/testthat_WSWR.R +++ b/tests/testthat/testthat_WSWR.R @@ -63,6 +63,13 @@ test_that("wrAdd() messages",{ tl=round(rnorm(30,500,200),0)) wae$wt <- round(3.33e-06*wae$tl^3.16+rnorm(30,0,50),1) + ## Simulate third data set + ruf <- data.frame(species=factor(rep(c("Ruffe"),30)), + tl=round(rnorm(30,130,20),0)) + ruf$wt <- round(3.03e-06*ruf$tl^3.26+rnorm(30,0,10),1) + + df2 <- rbind(wae,dbg,ruf,dbt) + ## bad units expect_error(wrAdd(wt~tl+species,df,units="inches"),"should be one of") @@ -98,6 +105,17 @@ test_that("wrAdd() messages",{ expect_error(wrAdd(wt~tl+species,wae, WsOpts=list(Walleye=list(junk=50))), "'junk' in 'WsOpts=' must be one of") + ## Need to use WsOpts for some, but not all, of the species + expect_error(wrAdd(wt~tl+species,data=df2), + "More than one Ws equation exists for \"Walleye\"") %>% + expect_output("Walleye") + expect_error(wrAdd(wt~tl+species,data=df2, + WsOpts=list(Walleye=list(group="overall"))), + "More than one Ws equation exists for \"Ruffe\"") %>% + expect_output("Ruffe") + expect_no_error(wrAdd(wt~tl+species,data=df2, + WsOpts=list(Walleye=list(group="overall"), + Ruffe=list(ref=75)))) }) From 39f3a49f91d3d11513e712ef8d89c2821aa2517e Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Mon, 24 Nov 2025 09:24:11 -0600 Subject: [PATCH 08/16] Major changes to groups, thesaurus, etc in psdAdd and wrAdd --- DESCRIPTION | 2 +- NEWS.md | 11 +- R/PSDWRtest.R | 44 ++++++++ R/PSDlit.R | 3 + R/WSlit.R | 2 + R/psdAdd.R | 165 ++++++++++++++++++---------- R/psdCalc.R | 52 ++++----- R/psdVal.R | 88 ++++++++++++--- R/wrAdd.R | 124 +++++++++++---------- R/wsVal.R | 134 +++++++++++++++------- data-raw/PSDlit.csv | 27 ++++- data-raw/WSlit.csv | 67 +++++++++-- data-raw/aaa_Make_Fake_PSDWR_Data.R | 132 ++++++++++++++++++++++ data/PSDWRtest.rda | Bin 0 -> 5366 bytes data/PSDlit.rdata | Bin 2480 -> 2812 bytes data/WSlit.rdata | Bin 5479 -> 6029 bytes man/PSDWRtest.Rd | 47 ++++++++ man/PSDlit.Rd | 3 + man/WSlit.Rd | 2 + man/psdAdd.Rd | 153 +++++++++++++++++--------- man/psdCalc.Rd | 45 ++++---- man/psdVal.Rd | 32 +++++- man/wrAdd.Rd | 134 ++++++++++++---------- man/wsVal.Rd | 71 +++++++----- tests/testthat/testthat_WSWR.R | 164 ++++++++++++++++----------- 25 files changed, 1061 insertions(+), 441 deletions(-) create mode 100644 R/PSDWRtest.R create mode 100644 data-raw/aaa_Make_Fake_PSDWR_Data.R create mode 100644 data/PSDWRtest.rda create mode 100644 man/PSDWRtest.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 036751d4..748e9900 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-10-1 +Date: 2025-12-1 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/NEWS.md b/NEWS.md index 8b49bf04..3fe1e1d1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,10 +1,13 @@ # FSA 0.10.9000 * `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 bug as described in [#136](https://github.com/fishR-Core-Team/FSA/issues/136)). Thanks to Dave Glover. -* `PSDlit`: Added info for Flier and Longear Sunfish. -* `wrAdd()`: Addressed bug similar to that for `psdAdd()`. -* `wSlit`: Added info for Flier and Longear Sunfish. This addresses [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). +* `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. Thanks to Dave Glover. +* `PSDlit`: Added info for Flier and Longear Sunfish to address [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). Also updated information info 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 `thesaurus` functionality. +* `PSDWRTest`: Added for testing PSD and relative weight functions. +* `wrAdd()`: Addressed bugs similar to those for `psdAdd()`. +* `wSlit`: Added info for Flier and Longear Sunfish to address [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). Also updated information info 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). +* `wsVal()`: Added `thesaurus` functionality. # 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). 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/psdAdd.R b/R/psdAdd.R index b5fcff7c..13704696 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. @@ -42,69 +43,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 some 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)) -#' dcs <- data.frame(species=factor(rep(c("Chinook Salmon"),20)), -#' tl=round(rnorm(20,450,50),0)) -#' df2 <- rbind(dbt,dlt,dcs) -#' -#' df2$psd <- psdAdd(tl~species,data=df2, -#' group=list("Brown Trout"="lentic", -#' "Chinook Salmon"="landlocked"), -#' addLens=list("Brown Trout"=240, -#' "Lake Trout"=425)) -#' peek(df2,n=20) +#' #===== 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 @@ -114,7 +158,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,...) { @@ -124,7 +169,7 @@ 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 ... change from factor to character if necessary specs <- as.character(unique(species)) @@ -136,7 +181,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`: ", @@ -159,7 +204,8 @@ psdAdd.default <- function(len,species,group=NULL,units=c("mm","cm","in"), 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) + 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]) @@ -182,7 +228,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,...) { @@ -202,6 +249,6 @@ 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,...) } diff --git a/R/psdCalc.R b/R/psdCalc.R index a960fe22..ac2129b6 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,thesaurus=NULL,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..62aa2287 100644 --- a/R/psdVal.R +++ b/R/psdVal.R @@ -3,14 +3,20 @@ #' @description Returns a vector with the five Gabelhouse lengths for a chosen species. #' #' @param species A string that contains the species name for which to find Gabelhouse lengths. See details. +#' @param thesaurus A named vector or 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 group A string that contains the sub-group of \code{species} for which to find the Gabelhouse lengths; e.g., things like \dQuote{landlocked}, \dQuote{lentic}. #' @param units A string that indicates the units for the returned lengths. Choices are \code{mm} for millimeters (DEFAULT), \code{cm} for centimeters, and \code{in} for inches. #' @param incl.zero A logical that indicates if a zero is included in the first position of the returned vector (DEFAULT) or not. This position will be named \dQuote{substock}. See details. #' @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. +#' +#' 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. #' #' 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. #' @@ -47,10 +53,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 +71,40 @@ #' #----- with a named vector in addLens= #' psdVal("Bluegill",units="in",addLens=c("MinLen"=7)) #' psdVal("Bluegill",units="in",addLens=c("MinSlot"=7,"MaxSlot"=9)) -#' +#' +#' #===== Values for species in PSDlit but named differently ... use thesaurus +#' #----- Single species in thesaurus ... not that useful +#' psdVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) +#' #----- Multiple species in thesaurus (i.e., possibly a global thesaurus) +#' thes <- c("Bluegill"="Bluegill Sunfish", +#' "Rainbow Darter"="Rainbow Perch", +#' "Pumpkinseed"="Pumpkinseed Sunfish", +#' "Lake Trout"="Lean Lake Trout") +#' psdVal("Bluegill Sunfish",thesaurus=thes) +#' psdVal("Lean Lake Trout",thesaurus=thes) +#' #' @export psdVal -psdVal <- function(species="List",group=NULL,units=c("mm","cm","in"), +psdVal <- function(species="List",thesaurus=NULL, + 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 <- iPrepPSDlit(thesaurus) + 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"] @@ -110,6 +133,45 @@ psdVal <- function(species="List",group=NULL,units=c("mm","cm","in"), } +# ============================================================================== +# 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 species in dat/PSDlit 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 +} + # ============================================================================== # Internal -- check species name against the 'dat' data.frame (usually PSDLit) # ============================================================================== diff --git a/R/wrAdd.R b/R/wrAdd.R index e5b45d62..52f87d75 100644 --- a/R/wrAdd.R +++ b/R/wrAdd.R @@ -14,6 +14,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,68 +32,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"))) #' -#' #===== 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) +#' #----- 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 #' -#' #===== Example with a species that has Ws eqns for multiple reference values -#' # and one must be specified with WsOpts -#' ruf <- data.frame(species=factor(rep(c("Ruffe"),30)), -#' tl=round(rnorm(30,130,20),0)) -#' ruf$wt <- round(3.03e-06*ruf$tl^3.26+rnorm(30,0,10),1) -#' # ruf$Wr <- wrAdd(wt~tl+species,data=ruf) # will err b/c multiple refs -#' ruf$Wr <- wrAdd(wt~tl+species,data=ruf, +#' 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 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(ruf,n=10) +#' peek(tmp,n=6) #' #' #===== Example with two uses of WsOpts (and one species without) -#' df2 <- rbind(wae[-4],dbg,ruf[-4]) -#' df2$Wr1 <- wrAdd(wt~tl+species,data=df2, -#' WsOpts=list(Walleye=list(group="overall"), -#' Ruffe=list(ref=75))) -#' peek(df2,n=15) +#' 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 @@ -102,7 +113,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 @@ -111,7 +122,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).") @@ -160,7 +171,6 @@ wrAdd.default <- function(wt,len,spec, #----- Return appropriate part of Wsdf (i.e., WSlit) Wsdf } - ###### END Internal Function ###### BEGIN Main Function @@ -173,7 +183,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,]) @@ -216,7 +226,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 ", @@ -232,5 +242,5 @@ 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,...) } diff --git a/R/wsVal.R b/R/wsVal.R index 87a8801b..bab8c5fc 100644 --- a/R/wsVal.R +++ b/R/wsVal.R @@ -10,14 +10,20 @@ #' #' 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. #' +#' 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} 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. +#' @param thesaurus A named vector or list for providing alternative species names (the values in the list) that correspond to specific names in \code{WSlit} (the names in the list). See details and examples. #' @param group A string that contains the sub-group of \code{species} for which to find the Ws coefficients; e.g., things like \dQuote{lotic}, \dQuote{lentic}, \dQuote{female}, \dQuote{male}. #' @param units A string that indicates whether the coefficients for the standard weight equation to be returned are in \code{"metric"} (DEFAULT; mm and g) or \code{"English"} (in and lbs) units. #' @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{psdAdd}). #' #' @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 +43,96 @@ #' #===== 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)") +#' +#' #===== Find equation for Bluegill Sunfish (aka Bluegill in WSlit) +#' # Note that this not that useful here as could just use "Bluegill" +#' # in first argument. This will be useful in wrAdd() +#' wsVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) +#' #' #===== 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 +141,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 +163,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 ", @@ -184,3 +196,41 @@ wsVal <- function(species="List",group=NULL, df } } + +# ============================================================================== +# 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/data-raw/PSDlit.csv b/data-raw/PSDlit.csv index d6fe7abd..d28b9b1d 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,16 +11,24 @@ 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) @@ -35,14 +44,22 @@ 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 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) @@ -56,14 +73,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,10,15,20,25,30,0,25,38,51,63,76,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 7ff65ce0..035eaeba 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),min.len not made clear (assumed same as Spotted Bass); same as Spotted Bass (Alabama subspecies) 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,6 +77,10 @@ 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 @@ -106,6 +131,12 @@ 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 @@ -121,6 +152,12 @@ Paddlefish,male,BL,English,75,RLP,11,NA,-3.063,2.91,NA,Brown and Murphy (1993),n 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 @@ -132,6 +169,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 @@ -169,17 +210,21 @@ 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),none +Spotted Bass (original),NA,TL,metric,75,RLP,100,NA,-5.392,3.215,NA,Wiens et al. (1996),none +Spotted Bass (Alabama subspecies),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 Alabama Bass 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) +Spriped 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 +Spriped 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 @@ -189,6 +234,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..59304cec --- /dev/null +++ b/data-raw/aaa_Make_Fake_PSDWR_Data.R @@ -0,0 +1,132 @@ +## 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.2)*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)) + + +PSDWRtest <- rbind(bgdf,bktdf,brt1df,brt2df,iaddf,lmbdf,lktdf,muedf,rufdf,waedf1,waedf2,yepdf) + +usethis::use_data(PSDWRtest,internal=FALSE,overwrite=TRUE) diff --git a/data/PSDWRtest.rda b/data/PSDWRtest.rda new file mode 100644 index 0000000000000000000000000000000000000000..4bb911b44d862a72ce2065d521f69a40701a9844 GIT binary patch literal 5366 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 U3aY!+RbKeJk}1N3g=vY{0I-v#p#T5? literal 0 HcmV?d00001 diff --git a/data/PSDlit.rdata b/data/PSDlit.rdata index 0d121fa4add3d8b68e21900912efceed6b85117e..f38b1eecf635e19b0892db44226aad2a21e07e5a 100644 GIT binary patch literal 2812 zcmV9y|KuA0Z^bR>(x6FtQK<7G$ucXju>_5t0xq z84ye{Zj<=-kT=1MNr{dTJCk#o}vk+`Y?zX)WI0v3v-Nn>`yIU4c$zF7VeUkM`S;dc| zvR#OGb{x+qd3V8cw)dpa^VAZOwkJ|;eHTdrXMf)nsUt5Ia#pnChGmjnQLR_!%+drt%csP#x`wJJOYuAJ;vRdPkgtN2xter`%- z08X{!`O;tsQFJW&6{XTD+Orr(Q91CP$cS!`iFv96NA-HTy~~~xQS<4MUtIQF5y16w zAj0x{ClZ0Z6vP#@(~A4!k4{jsi{-R7oh!aq5@sbX*JTIj!gksIVQ4h#N+9H#VqDcC zxct=LbE*QXdRCo1*}LU6)(Rejt$#R4?tpPhTo5R%K%P7GHBpB~NIf z_ctU*Lb|5w%!sb)DqYdDCJnfzd}Lnz$`?yg&PQvV%mabaTco!x5-jPPV zri+ua-%g|1_nfp>I*a>$6p50)ctDpmDGSt%X77QB?Tca*xcjE@Azjw&)G{Z$u{X+Y zBy&PkBcQ#<&kN`AbzDn%TCQlW)$$L{X^LC{I)s+n=s6&WS9StRs zn5Q0u#;w_r2-ifgouZS7ih3h;Y|3pedsRPkATsZ-P7)^;@z@}N_#i)Lri3A3h0aMf z7FxW%kxppoR7;ziYHzg6xuyG&{q1!4KA>KK3zkuD_MRPZFJA6!K|CAs^46 zh@0oh1r)qj(Fg)aA?{^ z{os$*|LNcA=jFeFX39s+b*UfD1E*QW&t*`|z+aV(Kq9a@B6#@{NqT!-KBd0eRiL%pJP1VKiIFp zh3|jFhkJH}$vH)y@H1tZ>p&6jEk;Riq5rWS_7`eqe86EPZ~DbN7VnWh&yw@=cp`(( zI{(l&98b*4+8+x<+4-Hug?$42c%G9)v40=2xM6ph);+dbQ^bS5TB@ClA|LqW`;k+d z#XZe$C1)zMkK~Sv2bz20hB-<~U^K$$w|#&r-N+ za9198rXZdiTbD&~#sUZaY?gI*L65VD|L(-^;IG&`)MK8>Io=aY4}7woLFd`J5hl;d zgZBsTD{haS!B*o8Qm3Q(3y?ZR)v5tGp2(phR#oXC{jW);e+NIHQPm-%H13ei3Hp9p z8##($m|_?rd-utw;``*7ra9`h3iaf+%7%IhQ8#LVjYs5jnCy*dql;|cB-%#vZfmjJ zqwf>M4-h{|vE*pn(PAIfMh~sgu|iIL#G?kcDK2%&Jfv9uK=W5=?pRI!s3o=2zu%;_ z!y26?TykU&W0vy5SfMya$(D-aGl~PXRXcita#HbrCx^p^vZFfdRg;mUwfz(qMjzob zLbQ|SO;8*Pw>kR$kSJ=Dr&!PfInoVjb;)Tt+$G%**&U!Uq}AXq#kEN`zmVe{t>2`% z(;Dvj_Yqnj?!|ylHzo9sBH=}Prkq7Wbe-$$*@oj+9I+YZ^9m%o}8Y=s|lS?4xA`bvdKxv2G`2M+YfE0 zTCz7>&vQeipUO2}pL0X?@>RoLV{PAxvn9N;ABVyoo0^}SaZYMAd*x{~&GPD5sFp+! zs(0Mv+~dS&x6lfwfyBB3<4L?Fg2d5O`tHgz*Awr7w(vvW{4m^+a&+vdR2KneA{<-)JdN8R}{cB=_cDUvq|e)XN$ zF1vn$i@ANW1N~*%6Uy6490ej)&7fxGT2?`p&NI4ZI(POx)XdXxBei;$q@41Z0?iE`)bb4}0n?7<^WAlNToWR=IzkGX~h!V$I&7xlVThz1Z~xZJp|lE4)&D z<@{NIYMMf$Wm*M#`n}xBYO{Ub@&VvOdH^QHRpZc zwX%1jdne<8rI|V(TSM0H zmdfBQ61n=GyniLlf?`G literal 2480 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 diff --git a/data/WSlit.rdata b/data/WSlit.rdata index e6120c2156230232798dca408b2d31eba17fe236..b762b180ec5358785bdd4f6ba528cd41d15f9a3d 100644 GIT binary patch literal 6029 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 Hx}*RAL=_B0 literal 5479 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 dejn`OgYb_dM~\% - 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 some 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)) -dcs <- data.frame(species=factor(rep(c("Chinook Salmon"),20)), - tl=round(rnorm(20,450,50),0)) -df2 <- rbind(dbt,dlt,dcs) - -df2$psd <- psdAdd(tl~species,data=df2, - group=list("Brown Trout"="lentic", - "Chinook Salmon"="landlocked"), - addLens=list("Brown Trout"=240, - "Lake Trout"=425)) -peek(df2,n=20) +#===== 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) } \references{ diff --git a/man/psdCalc.Rd b/man/psdCalc.Rd index 6c1d4fd9..21416f8f 100644 --- a/man/psdCalc.Rd +++ b/man/psdCalc.Rd @@ -74,48 +74,49 @@ See examples and \href{https://fishr-core-team.github.io/FSA/articles/Computing_ } \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)) } \references{ diff --git a/man/psdVal.Rd b/man/psdVal.Rd index 1ef6452a..3a4b58a4 100644 --- a/man/psdVal.Rd +++ b/man/psdVal.Rd @@ -6,17 +6,21 @@ \usage{ psdVal( species = "List", + thesaurus = NULL, group = NULL, units = c("mm", "cm", "in"), addLens = NULL, addNames = NULL, incl.zero = TRUE, - showJustSource = FALSE + showJustSource = FALSE, + dat = NULL ) } \arguments{ \item{species}{A string that contains the species name for which to find Gabelhouse lengths. See details.} +\item{thesaurus}{A named vector or 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.} + \item{group}{A string that contains the sub-group of \code{species} for which to find the Gabelhouse lengths; e.g., things like \dQuote{landlocked}, \dQuote{lentic}.} \item{units}{A string that indicates the units for the returned lengths. Choices are \code{mm} for millimeters (DEFAULT), \code{cm} for centimeters, and \code{in} for inches.} @@ -28,6 +32,8 @@ psdVal( \item{incl.zero}{A logical that indicates if a zero is included in the first position of the returned vector (DEFAULT) or not. This position will be named \dQuote{substock}. See details.} \item{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.} + +\item{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}).} } \value{ A vector of minimum values for length categories for the chosen species. @@ -38,6 +44,10 @@ Returns a vector with the five Gabelhouse lengths for a chosen species. \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. +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. + 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. @@ -59,10 +69,15 @@ psdVal("Bluegill",units="in",incl.zero=FALSE) 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= @@ -73,6 +88,17 @@ psdVal("Bluegill",units="in",addLens=c(7,9),addNames=c("MinSlot","MaxSlot")) psdVal("Bluegill",units="in",addLens=c("MinLen"=7)) psdVal("Bluegill",units="in",addLens=c("MinSlot"=7,"MaxSlot"=9)) +#===== Values for species in PSDlit but named differently ... use thesaurus +#----- Single species in thesaurus ... not that useful +psdVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) +#----- Multiple species in thesaurus (i.e., possibly a global thesaurus) +thes <- c("Bluegill"="Bluegill Sunfish", + "Rainbow Darter"="Rainbow Perch", + "Pumpkinseed"="Pumpkinseed Sunfish", + "Lake Trout"="Lean Lake Trout") +psdVal("Bluegill Sunfish",thesaurus=thes) +psdVal("Lean Lake Trout",thesaurus=thes) + } \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. diff --git a/man/wrAdd.Rd b/man/wrAdd.Rd index ef62bea5..8539e493 100644 --- a/man/wrAdd.Rd +++ b/man/wrAdd.Rd @@ -8,9 +8,17 @@ \usage{ wrAdd(wt, ...) -\method{wrAdd}{default}(wt, len, spec, units = c("metric", "English"), WsOpts = NULL, ...) - -\method{wrAdd}{formula}(wt, data, units = c("metric", "English"), ...) +\method{wrAdd}{default}( + wt, + len, + spec, + thesaurus = NULL, + units = c("metric", "English"), + WsOpts = NULL, + ... +) + +\method{wrAdd}{formula}(wt, data, thesaurus = NULL, units = c("metric", "English"), ...) } \arguments{ \item{wt}{A numeric vector that contains weight measurements or a formula of the form \code{wt~len+spec} where \dQuote{wt} generically represents the weight variable, \dQuote{len} generically represents the length variable, and \dQuote{spec} generically represents the species variable. Note that this formula can only contain three variables and they must be in the order of weight first, length second, species third.} @@ -21,6 +29,8 @@ wrAdd(wt, ...) \item{spec}{A character or factor vector that contains the species names. Not used if \code{wt} is a formula.} +\item{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.} + \item{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.} \item{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}}.} @@ -47,68 +57,78 @@ See examples and \href{https://fishr-core-team.github.io/FSA/articles/Computing_ } \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 - -#===== 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 with a species that has Ws eqns for multiple reference values -# and one must be specified with WsOpts -ruf <- data.frame(species=factor(rep(c("Ruffe"),30)), - tl=round(rnorm(30,130,20),0)) -ruf$wt <- round(3.03e-06*ruf$tl^3.26+rnorm(30,0,10),1) -# ruf$Wr <- wrAdd(wt~tl+species,data=ruf) # will err b/c multiple refs -ruf$Wr <- wrAdd(wt~tl+species,data=ruf, +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 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(ruf,n=10) +peek(tmp,n=6) #===== Example with two uses of WsOpts (and one species without) -df2 <- rbind(wae[-4],dbg,ruf[-4]) -df2$Wr1 <- wrAdd(wt~tl+species,data=df2, - WsOpts=list(Walleye=list(group="overall"), - Ruffe=list(ref=75))) -peek(df2,n=15) +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) } \references{ diff --git a/man/wsVal.Rd b/man/wsVal.Rd index 7b3db782..6939edf3 100644 --- a/man/wsVal.Rd +++ b/man/wsVal.Rd @@ -6,16 +6,20 @@ \usage{ wsVal( species = "List", + thesaurus = NULL, group = NULL, units = c("metric", "English"), ref = NULL, method = NULL, - simplify = FALSE + simplify = FALSE, + dat = NULL ) } \arguments{ \item{species}{A string that contains the species name for which to find Ws coefficients. See details.} +\item{thesaurus}{A named vector or list for providing alternative species names (the values in the list) that correspond to specific names in \code{WSlit} (the names in the list). See details and examples.} + \item{group}{A string that contains the sub-group of \code{species} for which to find the Ws coefficients; e.g., things like \dQuote{lotic}, \dQuote{lentic}, \dQuote{female}, \dQuote{male}.} \item{units}{A string that indicates whether the coefficients for the standard weight equation to be returned are in \code{"metric"} (DEFAULT; mm and g) or \code{"English"} (in and lbs) units.} @@ -25,6 +29,8 @@ wsVal( \item{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).} \item{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.} + +\item{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{psdAdd}).} } \value{ 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. @@ -43,6 +49,10 @@ See \code{\link{WSlit}} for more information about the meaning of each value ret 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. +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} 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. } \section{IFAR Chapter}{ @@ -53,49 +63,56 @@ See examples and \href{https://fishr-core-team.github.io/FSA/articles/Computing_ #===== 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)") + +#===== Find equation for Bluegill Sunfish (aka Bluegill in WSlit) +# Note that this not that useful here as could just use "Bluegill" +# in first argument. This will be useful in wrAdd() +wsVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) + #===== 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(len% + expect_message("The following species names were in \'thesaurus\' but do not") %>% + expect_error("There is no Ws equation in \'WSlit\' for \"Bluegill Sunfish\"") }) test_that("wrAdd() messages",{ - ## simulate data set - 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) - df$rnd <- runif(nrow(df)) - df$junk <- sample(c("Derek","Hugh","Ogle"),nrow(df),replace=TRUE) - - ## Simulate second data set - 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) - - ## Simulate third data set - ruf <- data.frame(species=factor(rep(c("Ruffe"),30)), - tl=round(rnorm(30,130,20),0)) - ruf$wt <- round(3.03e-06*ruf$tl^3.26+rnorm(30,0,10),1) - - df2 <- rbind(wae,dbg,ruf,dbt) + #===== Get data + #----- Species with no "issues" + random numeric variable + df1 <- subset(PSDWRtest, + species %in% c("Yellow Perch","Largemouth Bass","Iowa Darter")) + df1$rndn <- runif(nrow(df1)) + + #----- Species with some "issues" + df2 <- subset(PSDWRtest, + species %in% c("Bluegill Sunfish","Ruffe","Walleye","Iowa Darter")) - ## bad units - expect_error(wrAdd(wt~tl+species,df,units="inches"),"should be one of") + + #===== bad units + expect_error(wrAdd(wt~len+species,df1,units="inches"),"should be one of") - ## bad formulae - expect_error(wrAdd(~tl,df),"one variable") - expect_error(wrAdd(~tl+species,df),"one variable") - expect_error(wrAdd(~tl+species+wt,df),"left-hand-side") - expect_error(wrAdd(wt~tl,df),"one variable") - expect_error(wrAdd(wt~species,df),"one variable") - expect_error(wrAdd(wt~tl+rnd,df),"only one numeric") - expect_error(wrAdd(wt~species+junk,df),"only one numeric") - expect_error(wrAdd(wt~tl+species+junk,df),"one variable") - expect_error(wrAdd(wt+tl~species,df),"more than one variable") - expect_error(wrAdd(wt~tl+rnd+species,df),"one variable") + #===== bad formulae + expect_error(wrAdd(~len,df1),"must have one variable on the left-hand-side") + expect_error(wrAdd(~len+species,df1),"must have one variable on the left-hand-side") + expect_error(wrAdd(~len+species+wt,df1),"must have a left-hand-side") + expect_error(wrAdd(wt~len,df1),"must have one variable on the left-hand-side") + expect_error(wrAdd(wt~species,df1),"must have one variable on the left-hand-side") + expect_error(wrAdd(wt~len+rndn,df1),"must have one and only one numeric variable") + expect_error(wrAdd(wt~species+location,df1),"must have one and only one numeric variable") + expect_error(wrAdd(wt~len+species+location,df1),"must have one variable on the left-hand-side") + expect_error(wrAdd(wt+len~species,df1),"does not work with more than one variable on the") + expect_error(wrAdd(wt~len+rndn+species,df1),"must have one variable on the left-hand-side") - ## bad vector types - expect_error(wrAdd(species~wt+tl,df),"not numeric") - expect_error(wrAdd(df$species,df$wt,df$tl),"numeric") - expect_error(wrAdd(df$wt,df$species,df$tl),"numeric") - expect_error(wrAdd(df$wt,df$tl,df$rnd),"factor") + #===== bad vector types + expect_error(wrAdd(species~wt+len,df1),"Variable on left-hand-side of \'wt\' is not numeric") + expect_error(wrAdd(df1$species,df1$wt,df1$len),"\'wt\' must be numeric") + expect_error(wrAdd(df1$wt,df1$species,df1$len),"\'len\' must be numeric") + expect_error(wrAdd(df1$wt,df1$len,df1$rndn),"\'spec\' must be character or factor") - ## need to use WsOpts - expect_error(wrAdd(wt~tl+species,wae), - "More than one Ws equation exists for \"Walleye\"") %>% - expect_output("Walleye") - expect_error(wrAdd(wt~tl+species,wae, + #===== need to use WsOpts + expect_error(wrAdd(wt~len+species,df2), + "More than one Ws equation exists for \"Ruffe\"") %>% + expect_output("Ruffe") + expect_error(wrAdd(wt~len+species,df2, WsOpts=list(Bluegill=list(group="overall"))), + "More than one Ws equation exists for \"Ruffe\"") %>% + expect_output("Ruffe") + expect_error(wrAdd(wt~len+species,df2, + WsOpts=list(Ruffe=list(ref=50))), "More than one Ws equation exists for \"Walleye\"") %>% expect_output("Walleye") - expect_error(wrAdd(wt~tl+species,wae, - WsOpts=list(Walleye=list(ref=50))), + expect_error(wrAdd(wt~len+species,df2, + WsOpts=list(Ruffe=list(ref=50), + Walleye=list(ref=50))), "Use of 'ref=50' for \"Walleye\" did not return") - expect_error(wrAdd(wt~tl+species,wae, - WsOpts=list(Walleye=list(junk=50))), + expect_error(wrAdd(wt~len+species,df2, + WsOpts=list(Ruffe=list(junk=50))), "'junk' in 'WsOpts=' must be one of") - ## Need to use WsOpts for some, but not all, of the species - expect_error(wrAdd(wt~tl+species,data=df2), - "More than one Ws equation exists for \"Walleye\"") %>% - expect_output("Walleye") - expect_error(wrAdd(wt~tl+species,data=df2, - WsOpts=list(Walleye=list(group="overall"))), - "More than one Ws equation exists for \"Ruffe\"") %>% - expect_output("Ruffe") - expect_no_error(wrAdd(wt~tl+species,data=df2, + expect_no_error(wrAdd(wt~len+species,data=df2, WsOpts=list(Walleye=list(group="overall"), Ruffe=list(ref=75)))) + + #===== bad thesaurus + expect_error(wrAdd(wt~len+species,df2,thesaurus=c("Bluegill"), + WsOpts=list(Walleye=list(group="overall"), + Ruffe=list(ref=75))), + "Values in \'thesaurus\' must be named") + expect_error(wrAdd(wt~len+species,df2,thesaurus=c("Bluegill"=7), + WsOpts=list(Walleye=list(group="overall"), + Ruffe=list(ref=75))), + "Values in \'thesaurus\' must be strings of species names") + expect_error(wrAdd(wt~len+species,df2,thesaurus=factor(c("Bluegill"="Bluegill Sunfish")), + WsOpts=list(Walleye=list(group="overall"), + Ruffe=list(ref=75))), + "\'thesaurus\' must be either a vector or list") + tmp <- wrAdd(wt~len+species,df2,thesaurus=c("bluegill"="Bluegill Sunfish"), + WsOpts=list(Walleye=list(group="overall"), + Ruffe=list(ref=75))) %>% + expect_message("The following species names were in \'thesaurus\' but do not") }) ## Test Output Types ---- test_that("wsVal() results",{ - ## Do Bluegill results match ... example with no group or quad + #===== Do Bluegill results match ... example with no group or quad bg1 <- wsVal("Bluegill") bg2 <- WSlit[WSlit$species=="Bluegill" & WSlit$units=="metric",] bg2 <- bg2[,!names(bg2) %in% c("group","max.len","quad","comment")] @@ -134,7 +153,7 @@ test_that("wsVal() results",{ bg2 <- WSlit[WSlit$species=="Bluegill" & WSlit$units=="English",] bg2 <- bg2[,names(bg2) %in% c("species","min.len","int","slope")] expect_equal(bg1,bg2,ignore_attr=TRUE) - ## Do Ruffe results match ... example with quad + #===== Do Ruffe results match ... example with quad ruf1 <- wsVal("Ruffe",ref=75) ruf2 <- WSlit[WSlit$species=="Ruffe" & WSlit$units=="metric" & WSlit$ref=="75",] ruf2 <- ruf2[!names(ruf2) %in% c("group","comment")] @@ -143,7 +162,7 @@ test_that("wsVal() results",{ ruf2 <- WSlit[WSlit$species=="Ruffe" & WSlit$units=="metric" & WSlit$ref=="75",] ruf2 <- ruf2[,names(ruf2) %in% c("species","min.len","max.len","int","slope","quad")] expect_equal(ruf1,ruf2,ignore_attr=TRUE) - ## Do Walleye results match ... example with a sub-group + #===== Do Walleye results match ... example with a sub-group wae1 <- wsVal("Walleye",group="overall") wae2 <- WSlit[WSlit$species=="Walleye" & WSlit$group=="overall" & WSlit$units=="metric",] wae2 <- wae2[,!names(wae2) %in% c("max.len","quad","comment")] @@ -156,8 +175,21 @@ test_that("wsVal() results",{ wae2 <- WSlit[WSlit$species=="Walleye" & WSlit$group=="overall" & WSlit$units=="metric",] wae2 <- wae2[,names(wae2) %in% c("species","min.len","int","slope")] expect_equal(wae1,wae2,ignore_attr=TRUE) + #===== Do Walleye results match ... example with a sub-group in the species name + wae1 <- wsVal("Walleye (overall)") + wae2 <- WSlit[WSlit$species=="Walleye (overall)" & WSlit$units=="metric",] + wae2 <- wae2[,!names(wae2) %in% c("group","max.len","quad","comment")] + expect_equal(wae1,wae2,ignore_attr=TRUE) + wae1 <- wsVal("Walleye (overall)",units="English") + wae2 <- WSlit[WSlit$species=="Walleye (overall)" & WSlit$units=="English",] + wae2 <- wae2[,!names(wae2) %in% c("group","max.len","quad","comment")] + expect_equal(wae1,wae2,ignore_attr=TRUE) + wae1 <- wsVal("Walleye (overall)",simplify=TRUE) + wae2 <- WSlit[WSlit$species=="Walleye (overall)" & WSlit$units=="metric",] + wae2 <- wae2[,names(wae2) %in% c("species","min.len","int","slope")] + expect_equal(wae1,wae2,ignore_attr=TRUE) - ## + #===== Check list output expect_message(capture.output(wsVal("List")),"must be one of following") expect_output(suppressMessages(wsVal("List"))) }) From c7efe9ec124e9fec527d951ba735b886563ba84b Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Mon, 24 Nov 2025 17:41:26 -0600 Subject: [PATCH 09/16] Updated wr testthat --- NEWS.md | 1 + R/wrAdd.R | 2 +- R/wsVal.R | 2 +- data-raw/PSDlit.csv | 2 +- data-raw/aaa_Make_Fake_PSDWR_Data.R | 10 +- data/PSDWRtest.rda | Bin 5366 -> 5306 bytes data/PSDlit.rdata | Bin 2812 -> 2821 bytes inst/extdata/PSDWR_data4testthat.csv | 291 ++++++++++++++++++++++++++ inst/extdata/PSDWR_data4testthat.xlsx | Bin 0 -> 33228 bytes man/wrAdd.Rd | 2 +- man/wsVal.Rd | 2 +- tests/testthat/testthat_WSWR.R | 20 +- 12 files changed, 317 insertions(+), 15 deletions(-) create mode 100644 inst/extdata/PSDWR_data4testthat.csv create mode 100644 inst/extdata/PSDWR_data4testthat.xlsx diff --git a/NEWS.md b/NEWS.md index 3fe1e1d1..fa416015 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,7 @@ * `PSDWRTest`: Added for testing PSD and relative weight functions. * `wrAdd()`: Addressed bugs similar to those for `psdAdd()`. * `wSlit`: Added info for Flier and Longear Sunfish to address [#122](https://github.com/fishR-Core-Team/FSA/issues/122)). Also updated information info 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). +* `wrAdd()`: Added `thesaurus` functionality. Reworked examples in documentation. Reworked testing framework (especially expanded validation of results with hand-calculations). * `wsVal()`: Added `thesaurus` functionality. # FSA 0.10.0 diff --git a/R/wrAdd.R b/R/wrAdd.R index 52f87d75..80ec0ce1 100644 --- a/R/wrAdd.R +++ b/R/wrAdd.R @@ -44,7 +44,7 @@ #' tmp$wr2 <- wrAdd(tmp$wt,tmp$len,tmp$species) #' #----- same but using dplyr #' if (require(dplyr)) { -#' tmp <- tmp |> +#' tmp <- tmp %>% #' mutate(wr3=wrAdd(wt,len,species)) #' } #' #----- examine results diff --git a/R/wsVal.R b/R/wsVal.R index bab8c5fc..4b888a24 100644 --- a/R/wsVal.R +++ b/R/wsVal.R @@ -88,7 +88,7 @@ #' #' #----- Same as above but using dplyr #' if (require(dplyr)) { -#' yepdf <- PSDWRtest |> filter(species=="Yellow Perch") |> select(species,len,wt) |> +#' yepdf <- PSDWRtest %>% filter(species=="Yellow Perch") %>% select(species,len,wt) %>% #' mutate(ws=10^(wsYEP[["int"]]+wsYEP[["slope"]]*log10(len)), #' ws=ifelse(len - dplyr::mutate(wt=10^(-5.2)*len^3.1, - wt=round(wt+rnorm(dplyr::n(),wt*0,10),1), + 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_) @@ -126,7 +126,11 @@ yepdf <- data.frame(species="Yellow Perch", 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 index 4bb911b44d862a72ce2065d521f69a40701a9844..88275b7887c3e0dc3781faed9d624cc61667794d 100644 GIT binary patch literal 5306 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 literal 5366 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 U3aY!+RbKeJk}1N3g=vY{0I-v#p#T5? diff --git a/data/PSDlit.rdata b/data/PSDlit.rdata index f38b1eecf635e19b0892db44226aad2a21e07e5a..5c054ed84015a43b5e6be7ce6da2eee85c02cd80 100644 GIT binary patch delta 2764 zcmV;-3N!Wm6@?a%6o26#gpdGRArpy`k%b7bAcHMM%Ys0Okc3#th}c!~z&7j@vpZyd zq{27Z*GTS?C*c8-cgR()^8``4cg{E4eb`wD;EFG_Rjsq@okH2prG5L&^a|>4~a@0lKTE z&ev2uQuV&dv+YczJRT+*&_vB#YC7FzhjL~Zx>SgREgxLZVt?6jtM;0^y(a#_rMVTWx0Fn=_fbtMpTO);)&5nO)i?>SY0RlTdup6uOnycNa@dKjyVb#HQFuq$Zq zXnSwfukH#bU|zbExax<(UU6Wv^I0733D1k=0yMWKI@;WZaz|7gPe9ji=yXl@b3c&C z2dbC$;HN(o7OOHbeT%O-rIIJK&<7flBOzVYb!J3Ybbpnu=v|WrTv^R1mH?*R+AYNu z5k-D_N{ckY#SQQ8WG z6Gp70JyLPB(0%K!gs9$iMgz64`|3Pxq;_##9=NE-rJ@t>rgJaXxke)w%f933Yx|`n zNVby+>MKKE8ebe}`E^BsbnG@dF8)Y{Vx`pmy{9c`thOqs08!&H302(k~A@*pK zr;6OvXrg%+=Gq!U^?)zapsIvOo=Zs~rcKP~+^R<4^i z%*W6F@6#j4+x(4$$=gJ~s3r6^@k2y^L-GOQ$B4GE^`HaC$hm#?)gGULmld>!a` zMt|HK2gC%`7C3;mBg5y#h*-yHG4W8u)Wi~7Oeq#0)#ZyYcw%1G{#YQ&&hIoX>=WR} z^PD7#{riZ;4ZF*);%e9U^@SR#t^fa41s@OuY%@cRgLUaT2* z@;32LiT=)NO_zy&gZal%nveYtzliTq2Ic4Cea3%I=REA;`E6!6kt6Ry-o&9$Gwn?= zJ@Db@0x0qT-smq@x3oUU6O%Ir8UY@YP6ir(SqweOj3<^EYBL3Tn-@#w8d8o%clXJW$m>&3KJ%i4(b)!tq^)}EFQ*YE*T|Z5nsT<^+AerHvfLFhVhZ z43oY4z^r+K%uSnkpH3E~Hd zpQKoFH124z*YmC=`1aBo9V_J2PdsXHi{etJ%tMOh4>W(3=8h@5WLy7!gVv5{beeF< zkv)uA$_rzK;zZ0Uj?X9#)K=~21a15yMvm4FP+S=OgwH6^E}Az% zaVXs8==(#Ws8OC`K@a3eH;lSaKFHxN>4wSfAdO+I26rj0O|tog9PeoTCe5AJaM!<& z(%Rb^RhX$?+K&hy#HxDpfi}J+ED-ZOiV;3lO;wH8D7Pze1aj=Lq3ozrtK4LNJfyY5 z6c@&T)#!0WduZMq;h}o__w;?0V!1{93oGfJO&WTQRL+kmpJBpdmUJUz_lDItdy=~t zcLJVYzdKCm2JtJ2!Tc8S_&dh;#N$kTp3o!D{aNzIHDg`shx4yMX?~ITZ&{q6uSvgt z*qm^1a&*Qj5H%&X~?=y$^w}-9i_cZ?{&Ho|anr{6-^AAnG zi0@Sf#hr$`e3kK2HPhZp^2eVYHkcf^12_D>f&LA}iMttn1ByI=H~On+(zHIv6aBGP zGuMH_Kk{RLpR>$&|E?7s_4Zb1i^z7o343gMa(Wi8CUiYHaH2@bCMO|(8(J$1Z$Gr1 zYRTSkJANe>Tu;0Y_uTr7Dd6I3Upn4Vu`(@UDvp=bNpjeJ8PF062 z-I{|-u{_?Bv*5W9-a$R=sk314SMouj^{=P4N2F2Aa+C$h>|9&h>9OLTb^jh+M~diM`c6M@U~qsy`_BWEtP2A z8nTABR0eOU;8N(v!M5NKZF}mS+XNyAJ4#OEOzZ>_JvO}`U7q_BKvn(e;M1D?=fj5& Sf0g7vYWx?4gMz6AGynk4OR2p8 delta 2782 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 diff --git a/inst/extdata/PSDWR_data4testthat.csv b/inst/extdata/PSDWR_data4testthat.csv new file mode 100644 index 00000000..90a46b46 --- /dev/null +++ b/inst/extdata/PSDWR_data4testthat.csv @@ -0,0 +1,291 @@ +species,location,sex,species2,len,wt,psd,ws,wr +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,66,5.1,substock,NA,NA +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,85,NA,stock,10.56703529,NA +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,97,16.6,stock,16.3732567,101.3848393 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,101,15.9,stock,18.72102725,84.93123687 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,102,18.3,stock,19.34274781,94.60910197 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,104,21.9,stock,20.62920792,106.1601593 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,108,21.5,stock,23.37938987,91.96133912 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,108,22.9,stock,23.37938987,97.94951934 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,108,27.2,stock,23.37938987,116.3417872 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,114,30.1,stock,27.97025895,107.6143058 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,124,38.5,stock,36.96462528,104.1536326 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,137,50.7,stock,51.44763325,98.5468073 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,143,61.8,stock,59.3054083,104.2063477 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,149,74,stock,67.96505396,108.8794839 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,151,81.1,quality,71.03748171,114.1650831 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,154,82.4,quality,75.82609843,108.6697083 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,154,NA,quality,75.82609843,NA +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,155,75.1,quality,77.47113365,96.9393327 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,156,72.5,quality,79.14093341,91.60872494 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,156,81.7,quality,79.14093341,103.2335562 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,163,95.9,quality,91.54067199,104.7621761 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,165,93.6,quality,95.31840335,98.19719667 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,165,104.5,quality,95.31840335,109.632554 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,179,NA,quality,124.87073,NA +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,184,151.5,quality,136.8156888,110.7329148 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,186,161.1,quality,141.8093685,113.6032137 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,191,138.3,quality,154.8483727,89.31317622 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,207,216.2,preferred,202.1890658,106.9296202 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,209,213.7,preferred,208.7397143,102.3763018 +Bluegill Sunfish,Bass Lake,NA,Bluegill Sunfish,239,346.6,preferred,325.6622653,106.4292787 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),135,27.8,stock,26.5720881,104.6210591 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),147,38.3,stock,34.60873215,110.6657124 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),164,51.9,stock,48.60270721,106.7841752 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),166,56.1,stock,50.4655949,111.1648443 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),172,62.3,stock,56.34362316,110.571519 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),204,NA,quality,95.67146175,NA +Brook Trout,Trout Lake,NA,Brook Trout (lotic),206,108.2,quality,98.61204945,109.7228996 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),208,110.7,quality,101.6132936,108.9424386 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),229,150.6,quality,136.9523541,109.9652511 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),241,174.7,quality,160.4718588,108.8664401 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),245,185.5,quality,168.8816097,109.8402605 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),246,187.6,quality,171.0297407,109.6885251 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),249,193.9,quality,177.5851204,109.1870758 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),261,225.1,quality,205.5111996,109.5317435 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),271,253.4,quality,230.9424185,109.7243207 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),276,268.2,quality,244.4223311,109.7281082 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),279,276.8,quality,252.7608707,109.5106213 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),285,296,quality,270.0123326,109.6246224 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),291,316.4,quality,288.0447373,109.8440482 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),336,492.3,quality,450.0189248,109.3953994 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),339,505.1,quality,462.6042981,109.1861883 +Brook Trout,Trout Lake,NA,Brook Trout (lotic),340,512.6,quality,466.8518451,109.7992876 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),161,25.5,substock,42.32547572,60.24740317 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),172,27.8,substock,52.27305224,53.18227807 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),203,53.9,stock,88.74468355,60.73603268 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),206,54.4,stock,93.00191728,58.49341776 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),209,54,stock,97.39737179,55.4429745 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),215,67.3,stock,106.612577,63.1257605 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),225,78.1,stock,123.2738509,63.35487976 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),258,111.1,stock,190.8593062,58.21041803 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),286,158.6,stock,265.2363909,59.79571636 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),295,176.6,stock,292.8272703,60.30859074 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),297,NA,stock,299.2155082,NA +Brown Trout,Brushy Creek,F,Brown Trout (lentic),298,187.4,stock,302.4452356,61.96163072 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),299,174.8,stock,305.6988293,57.18046105 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),308,203,quality,336.0709615,60.40390967 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),314,182.6,quality,357.4318887,51.08665617 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),316,261.1,quality,364.754402,71.58241231 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),318,204.4,quality,372.1793056,54.919765 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),324,202.4,quality,395.0761042,51.23063578 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),326,253,quality,402.9183201,62.79188296 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),333,232.2,quality,431.2080718,53.84871369 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),338,233.3,quality,452.2305951,51.58872542 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),339,223,quality,456.5179265,48.848027 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),348,NA,quality,496.3683768,NA +Brown Trout,Brushy Creek,M,Brown Trout (lentic),423,575.7,preferred,925.829753,62.18205865 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),442,720.1,preferred,1065.316683,67.59492377 +Brown Trout,Brushy Creek,M,Brown Trout (lentic),447,642,preferred,1104.287685,58.13702433 +Brown Trout,Brushy Creek,F,Brown Trout (lentic),455,754.1,preferred,1168.660596,64.52686117 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),128,25,substock,NA,NA +Brown Trout,Trout Lake,NA,Brown Trout (lotic),134,29.9,substock,NA,NA +Brown Trout,Trout Lake,NA,Brown Trout (lotic),138,32.7,substock,NA,NA +Brown Trout,Trout Lake,NA,Brown Trout (lotic),143,40.9,substock,32.56826858,125.5823591 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),208,117.3,stock,98.73416814,118.8038571 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),220,116,stock,116.5657964,99.51461198 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),230,122.9,quality,132.9579758,92.43522193 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),232,144.8,quality,136.4094429,106.151009 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),245,164.4,quality,160.299294,102.558156 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),249,171.8,quality,168.1705976,102.158167 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),254,181.5,quality,178.3642456,101.7580622 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),264,NA,quality,199.9620698,NA +Brown Trout,Trout Lake,NA,Brown Trout (lotic),281,257.4,quality,240.5308062,107.0133194 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),333,461.3,preferred,397.5895226,116.0241842 +Brown Trout,Trout Lake,NA,Brown Trout (lotic),374,583,preferred,560.6604774,103.984501 +Iowa Darter,Bass Lake,NA,Iowa Darter,43,0.3,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,43,0.6,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,46,NA,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,46,NA,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,46,NA,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,48,0.7,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,48,0.8,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,48,NA,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,51,0.6,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,51,0.8,NA,NA,NA +Iowa Darter,Bass Lake,NA,Iowa Darter,56,0.9,NA,NA,NA +Largemouth Bass,Bass Lake,NA,Largemouth Bass,188,55.4,substock,82.28461484,67.32728847 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,191,64.6,substock,86.66070365,74.54359044 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,196,61.4,substock,94.30921318,65.10498596 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,196,69.8,substock,94.30921318,74.011857 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,200,77.5,stock,100.7560599,76.91845046 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,202,85,stock,104.0914437,81.65896922 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,204,78.1,stock,107.5027411,72.64931034 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,208,76.6,stock,114.5569112,66.86632799 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,226,103.8,stock,150.3131311,69.05584314 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,273,172.3,stock,278.9718251,61.7625095 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,284,201.8,stock,317.4760198,63.56385597 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,285,218.3,stock,321.1494827,67.97457625 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,286,246.7,stock,324.8523602,75.94219105 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,287,228.3,stock,328.5847837,69.47978462 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,288,246.4,stock,332.3468849,74.1394041 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,292,206.4,stock,347.6947017,59.36242312 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,294,242.9,stock,355.550106,68.31667208 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,294,248.3,stock,355.550106,69.83544536 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,295,271.7,stock,359.5236451,75.57221999 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,296,236.6,stock,363.5279189,65.08440966 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,301,259.4,quality,384.014957,67.54945224 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,306,311.9,quality,405.2903179,76.95718013 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,312,259.9,quality,431.8848663,60.17807528 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,319,379.9,quality,464.4157135,81.80171105 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,330,NA,quality,518.914881,NA +Largemouth Bass,Bass Lake,NA,Largemouth Bass,333,349.3,quality,534.5150973,65.34894932 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,333,395,quality,534.5150973,73.8987546 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,335,390.6,quality,545.094316,71.65732398 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,341,483.2,quality,577.7036114,83.64150587 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,347,472.4,quality,611.6435087,77.23453176 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,362,467.6,quality,702.5110364,66.56123189 +Largemouth Bass,Bass Lake,NA,Largemouth Bass,396,726.3,preferred,942.4457136,77.0654468 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,276,197.8,substock,NA,NA +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,312,276,stock,260.0314108,106.1410232 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,458,895.7,stock,904.0018965,99.08165054 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,471,913.1,stock,989.9787318,92.2343047 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,473,1106.5,stock,1003.689227,110.2432875 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,478,1075.6,stock,1038.53934,103.5685369 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,511,1157.3,quality,1289.835251,89.72463727 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,524,1240.2,quality,1399.424128,88.62216786 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,525,1156.5,quality,1408.111673,82.13126997 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,529,1480,quality,1443.235196,102.5473883 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,558,1539.7,quality,1716.226524,89.71426429 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,564,1526.6,quality,1776.85493,85.91584909 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,580,1877.7,quality,1945.751021,96.50258329 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,595,1937.8,quality,2113.888474,91.66992601 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,601,1973,quality,2183.868762,90.3442567 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,680,3403.4,preferred,3260.79826,104.3732156 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,709,3488.7,preferred,3734.200901,93.42561079 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,724,4312.4,preferred,3996.790513,107.8965732 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,736,3830.4,preferred,4215.852282,90.85707335 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,737,3990.9,preferred,4234.473951,94.24783447 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,752,5291.2,preferred,4520.673175,117.0445152 +Lean Lake Trout,Trout Lake,F,Lean Lake Trout,781,5994,preferred,5111.463406,117.2658302 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,785,4678.7,preferred,5196.930463,90.02814322 +Lean Lake Trout,Trout Lake,M,Lean Lake Trout,829,6924,memorable,6203.374581,111.6166678 +Muskellunge,Long Lake,F,Muskellunge (female),542,1167.2,stock,1063.059608,109.796289 +Muskellunge,Long Lake,F,Muskellunge (female),593,1460.1,stock,1435.498278,101.7138106 +Muskellunge,Long Lake,F,Muskellunge (female),766,2768.2,quality,3375.391019,82.01123911 +Muskellunge,Long Lake,F,Muskellunge (female),1090,11590.9,memorable,10964.89565,105.7091683 +Muskellunge,Long Lake,M,Muskellunge (male),572,1355.6,stock,1332.754365,101.714167 +Muskellunge,Long Lake,M,Muskellunge (male),604,1669.3,stock,1590.248028,104.9710467 +Muskellunge,Long Lake,M,Muskellunge (male),680,2756.5,stock,2336.099959,117.9958071 +Muskellunge,Long Lake,M,Muskellunge (male),716,2761.9,stock,2761.803384,100.0034983 +Muskellunge,Long Lake,M,Muskellunge (male),786,3576.5,quality,3738.059087,95.67799537 +Muskellunge,Long Lake,M,Muskellunge (male),947,8109.2,quality,6843.144046,118.5010858 +Muskellunge,Long Lake,M,Muskellunge (male),965,8692.1,quality,7274.298726,119.4905561 +Muskellunge,Long Lake,M,Muskellunge (male),978,8879.3,preferred,7597.130451,116.8770243 +Muskellunge,Long Lake,M,Muskellunge (male),1045,11109.7,preferred,9419.597863,117.9424022 +Muskellunge,Long Lake,U,Muskellunge (overall),683,2723.2,stock,2282.700005,119.2973231 +Muskellunge,Long Lake,U,Muskellunge (overall),856,6312.3,quality,4835.877239,130.5306088 +Muskellunge,Long Lake,U,Muskellunge (overall),940,8965.1,quality,6601.613786,135.8016432 +Muskellunge,Long Lake,U,Muskellunge (overall),1097,11376.4,memorable,11032.8328,103.1140434 +Ruffe,Round Lake,NA,Ruffe,19,0.1,substock,NA,NA +Ruffe,Round Lake,NA,Ruffe,26,0.1,substock,NA,NA +Ruffe,Round Lake,NA,Ruffe,95,9.4,quality,10.55732536,89.03770301 +Ruffe,Round Lake,NA,Ruffe,105,11.7,quality,14.32531794,81.67357997 +Ruffe,Round Lake,NA,Ruffe,106,11.7,quality,14.74948502,79.32480343 +Ruffe,Round Lake,NA,Ruffe,114,17.5,quality,18.48152114,94.68917557 +Ruffe,Round Lake,NA,Ruffe,118,20.6,quality,20.58697,100.0632924 +Ruffe,Round Lake,NA,Ruffe,137,25.2,preferred,33.08087874,76.17693652 +Ruffe,Round Lake,NA,Ruffe,143,31.7,memorable,37.98916046,83.44485537 +Ruffe,Round Lake,NA,Ruffe,151,40.6,memorable,45.34913131,89.52762452 +Ruffe,Round Lake,NA,Ruffe,152,36.1,memorable,46.33839166,77.90516396 +Ruffe,Round Lake,NA,Ruffe,175,56.4,trophy,73.85609555,76.36471923 +Ruffe,Round Lake,NA,Ruffe,189,89.3,trophy,95.69305504,93.31920688 +Ruffe,Round Lake,NA,Ruffe,196,102.5,trophy,108.2707524,94.67007266 +Walleye,Bass Lake,NA,Walleye (30-149 mm),75,3.5,substock,3.763143371,93.00735197 +Walleye,Bass Lake,NA,Walleye (30-149 mm),75,3.6,substock,3.763143371,95.66470489 +Walleye,Bass Lake,NA,Walleye (30-149 mm),75,3.8,substock,3.763143371,100.9794107 +Walleye,Bass Lake,NA,Walleye (30-149 mm),82,5.1,substock,4.861070755,104.9151567 +Walleye,Bass Lake,NA,Walleye (30-149 mm),84,4.8,substock,5.209034954,92.14758668 +Walleye,Bass Lake,NA,Walleye (30-149 mm),84,5,substock,5.209034954,95.98706946 +Walleye,Bass Lake,NA,Walleye (30-149 mm),85,NA,substock,5.388934412,NA +Walleye,Bass Lake,NA,Walleye (30-149 mm),86,5.2,substock,5.572833357,93.30980611 +Walleye,Bass Lake,NA,Walleye (30-149 mm),93,7.2,substock,6.97553592,103.2178758 +Walleye,Bass Lake,NA,Walleye (30-149 mm),96,7,substock,7.640753123,91.61400568 +Walleye,Bass Lake,NA,Walleye (30-149 mm),96,9,substock,7.640753123,117.7894359 +Walleye,Bass Lake,NA,Walleye (30-149 mm),108,10.9,substock,10.71254735,101.749842 +Walleye,Bass Lake,NA,Walleye (30-149 mm),110,12,substock,11.29160335,106.2736587 +Walleye,Bass Lake,NA,Walleye (30-149 mm),121,15.9,substock,14.84264251,107.123782 +Walleye,Bass Lake,NA,Walleye (30-149 mm),123,15.4,substock,15.55742675,98.98809264 +Walleye,Bass Lake,NA,Walleye (30-149 mm),127,16.8,substock,17.05347447,98.5136491 +Walleye,Bass Lake,NA,Walleye (30-149 mm),132,19.1,substock,19.05138742,100.2551656 +Walleye,Bass Lake,NA,Walleye (overall),228,117,substock,110.9769573,105.4272912 +Walleye,Bass Lake,NA,Walleye (overall),258,145.7,stock,164.4184936,88.61533565 +Walleye,Bass Lake,NA,Walleye (overall),261,190.8,stock,170.575563,111.8565852 +Walleye,Bass Lake,NA,Walleye (overall),266,194.2,stock,181.1855691,107.182929 +Walleye,Bass Lake,NA,Walleye (overall),268,218.4,stock,185.553284,117.7020397 +Walleye,Bass Lake,F,Walleye (overall),347,431.3,stock,421.9371158,102.2190236 +Walleye,Bass Lake,M,Walleye (overall),348,448.6,stock,425.8160194,105.3506631 +Walleye,Bass Lake,F,Walleye (overall),381,540.6,quality,567.9909587,95.17757135 +Walleye,Bass Lake,F,Walleye (overall),385,519.6,quality,587.1717057,88.49200242 +Walleye,Bass Lake,M,Walleye (overall),390,527.9,quality,611.7661602,86.29114102 +Walleye,Bass Lake,M,Walleye (overall),392,667.9,quality,621.7985331,107.4142129 +Walleye,Bass Lake,M,Walleye (overall),401,752.5,quality,668.3425401,112.5919652 +Walleye,Bass Lake,M,Walleye (overall),402,698.2,quality,673.657034,103.6432435 +Walleye,Bass Lake,M,Walleye (overall),411,729.4,quality,722.7980855,100.913383 +Walleye,Bass Lake,M,Walleye (overall),418,698.4,quality,762.6768708,91.57220137 +Walleye,Bass Lake,M,Walleye (overall),419,582.7,quality,768.4941981,75.82360433 +Walleye,Bass Lake,M,Walleye (overall),428,787.8,quality,822.2259617,95.81307775 +Walleye,Bass Lake,M,Walleye (overall),431,962.6,quality,840.6935571,114.5006991 +Walleye,Bass Lake,F,Walleye (overall),432,841.7,quality,846.9120554,99.38458128 +Walleye,Bass Lake,M,Walleye (overall),434,794.6,quality,859.4435168,92.45517413 +Walleye,Bass Lake,M,Walleye (overall),449,851.3,quality,957.5101016,88.90767822 +Walleye,Bass Lake,F,Walleye (overall),454,848.7,quality,991.830849,85.56902629 +Walleye,Bass Lake,F,Walleye (overall),470,1293.1,quality,1107.315013,116.7779705 +Walleye,Bass Lake,M,Walleye (overall),490,1313,quality,1264.222556,103.8582957 +Walleye,Bass Lake,M,Walleye (overall),515,1586.3,preferred,1480.97248,107.1120511 +Walleye,Bass Lake,F,Walleye (overall),549,1603.9,preferred,1814.847157,88.37658831 +Walleye,Bass Lake,F,Walleye (overall),560,1762.5,preferred,1933.027025,91.17823894 +Walleye,Bass Lake,F,Walleye (overall),564,1827.9,preferred,1977.277164,92.4453098 +Walleye,Bass Lake,M,Walleye (overall),571,2390.1,preferred,2056.377409,116.2286645 +Walleye,Bass Lake,M,Walleye (overall),572,1878.4,preferred,2067.851616,90.83823935 +Walleye,Bass Lake,M,Walleye (overall),603,2330.6,preferred,2445.733051,95.29249313 +Walleye,Bass Lake,F,Walleye (overall),653,3286.3,memorable,3150.822343,104.2997555 +Yellow Perch,Bass Lake,F,Yellow Perch,105,12.5,substock,13.88166105,90.04686078 +Yellow Perch,Bass Lake,F,Yellow Perch,120,17.8,substock,21.36758424,83.3037549 +Yellow Perch,Bass Lake,F,Yellow Perch,122,23.4,substock,22.53939492,103.8182262 +Yellow Perch,Bass Lake,F,Yellow Perch,128,27.8,substock,26.32014042,105.6225368 +Yellow Perch,Bass Lake,F,Yellow Perch,131,30.6,stock,28.3652284,107.8785602 +Yellow Perch,Bass Lake,F,Yellow Perch,133,26.9,stock,29.78796263,90.30493403 +Yellow Perch,Bass Lake,F,Yellow Perch,136,34,stock,32.01331692,106.205802 +Yellow Perch,Bass Lake,F,Yellow Perch,138,32.3,stock,33.55903384,96.24830128 +Yellow Perch,Bass Lake,M,Yellow Perch,146,42.8,stock,40.25869789,106.31243 +Yellow Perch,Bass Lake,F,Yellow Perch,150,40.2,stock,43.931372,91.50636133 +Yellow Perch,Bass Lake,F,Yellow Perch,150,44.8,stock,43.931372,101.9772385 +Yellow Perch,Bass Lake,F,Yellow Perch,151,NA,stock,44.88441196,NA +Yellow Perch,Bass Lake,M,Yellow Perch,154,44.9,stock,47.82906911,93.87596464 +Yellow Perch,Bass Lake,F,Yellow Perch,154,49.5,stock,47.82906911,103.4935468 +Yellow Perch,Bass Lake,M,Yellow Perch,158,NA,stock,51.95919224,NA +Yellow Perch,Bass Lake,F,Yellow Perch,162,50.4,stock,56.3291888,89.47403837 +Yellow Perch,Bass Lake,F,Yellow Perch,174,71.8,stock,70.95354063,101.1929769 +Yellow Perch,Bass Lake,F,Yellow Perch,189,90,stock,92.67692754,97.1115491 +Yellow Perch,Bass Lake,F,Yellow Perch,196,104.9,stock,104.2286495,100.6441132 +Yellow Perch,Bass Lake,F,Yellow Perch,197,88.7,stock,105.9560868,83.7139259 +Yellow Perch,Bass Lake,M,Yellow Perch,206,117.7,quality,122.402735,96.15798212 +Yellow Perch,Bass Lake,F,Yellow Perch,225,176.3,quality,162.7606942,108.3185353 +Yellow Perch,Bass Lake,F,Yellow Perch,240,215.9,quality,200.4851966,107.6887489 +Yellow Perch,Bass Lake,M,Yellow Perch,244,248.8,quality,211.4799208,117.6471029 +Yellow Perch,Bass Lake,M,Yellow Perch,248,226.5,quality,222.8840184,101.6223602 +Yellow Perch,Bass Lake,M,Yellow Perch,249,228.7,quality,225.7999758,101.2843332 +Yellow Perch,Bass Lake,M,Yellow Perch,252,242.2,preferred,234.7057594,103.1930365 +Yellow Perch,Bass Lake,F,Yellow Perch,257,285,preferred,250.0828951,113.9622124 +Yellow Perch,Bass Lake,F,Yellow Perch,260,269.5,preferred,259.6354047,103.799403 +Yellow Perch,Bass Lake,M,Yellow Perch,261,289.6,preferred,262.8747294,110.1665423 +Yellow Perch,Bass Lake,F,Yellow Perch,262,286.5,preferred,266.1418497,107.6493608 +Yellow Perch,Bass Lake,M,Yellow Perch,264,305,preferred,272.7600013,111.8199144 +Yellow Perch,Bass Lake,F,Yellow Perch,265,272.7,preferred,276.111295,98.76452176 +Yellow Perch,Bass Lake,F,Yellow Perch,266,271.4,preferred,279.4909091,97.1051262 +Yellow Perch,Bass Lake,F,Yellow Perch,266,297.9,preferred,279.4909091,106.586651 +Yellow Perch,Bass Lake,F,Yellow Perch,274,321.8,preferred,307.5631625,104.628915 +Yellow Perch,Bass Lake,M,Yellow Perch,277,283.4,preferred,318.5735053,88.95906135 +Yellow Perch,Bass Lake,F,Yellow Perch,278,315.6,preferred,322.3032545,97.92020268 +Yellow Perch,Bass Lake,M,Yellow Perch,279,373,preferred,326.0630424,114.395056 +Yellow Perch,Bass Lake,M,Yellow Perch,280,346.9,preferred,329.8530022,105.168059 +Yellow Perch,Bass Lake,F,Yellow Perch,281,348.1,preferred,333.6732668,104.3236107 +Yellow Perch,Bass Lake,F,Yellow Perch,284,348.7,preferred,345.3172219,100.9796146 +Yellow Perch,Bass Lake,M,Yellow Perch,288,419,preferred,361.2748551,115.9781795 +Yellow Perch,Bass Lake,F,Yellow Perch,291,422.6,preferred,373.5720318,113.1241003 +Yellow Perch,Bass Lake,M,Yellow Perch,299,411.3,preferred,407.7725042,100.8650646 +Yellow Perch,Bass Lake,F,Yellow Perch,306,360.8,memorable,439.4203924,82.10816027 +Yellow Perch,Bass Lake,M,Yellow Perch,312,455.9,memorable,467.8636867,97.44291189 +Yellow Perch,Bass Lake,F,Yellow Perch,313,507.2,memorable,472.7246079,107.2929125 +Yellow Perch,Bass Lake,M,Yellow Perch,347,675.2,memorable,659.5750265,102.3689456 diff --git a/inst/extdata/PSDWR_data4testthat.xlsx b/inst/extdata/PSDWR_data4testthat.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2a16ef808df25eea8245133d0008bfe6064256b9 GIT binary patch literal 33228 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 literal 0 HcmV?d00001 diff --git a/man/wrAdd.Rd b/man/wrAdd.Rd index 8539e493..f8dc4ffb 100644 --- a/man/wrAdd.Rd +++ b/man/wrAdd.Rd @@ -69,7 +69,7 @@ tmp$wr1 <- wrAdd(wt~len+species,data=tmp) tmp$wr2 <- wrAdd(tmp$wt,tmp$len,tmp$species) #----- same but using dplyr if (require(dplyr)) { - tmp <- tmp |> + tmp <- tmp \%>\% mutate(wr3=wrAdd(wt,len,species)) } #----- examine results diff --git a/man/wsVal.Rd b/man/wsVal.Rd index 6939edf3..f8dab386 100644 --- a/man/wsVal.Rd +++ b/man/wsVal.Rd @@ -108,7 +108,7 @@ peek(yepdf,n=6) #----- Same as above but using dplyr if (require(dplyr)) { - yepdf <- PSDWRtest |> filter(species=="Yellow Perch") |> select(species,len,wt) |> + yepdf <- PSDWRtest \%>\% filter(species=="Yellow Perch") \%>\% select(species,len,wt) \%>\% mutate(ws=10^(wsYEP[["int"]]+wsYEP[["slope"]]*log10(len)), ws=ifelse(len% expect_message("The following species names were in \'thesaurus\' but do not") %>% @@ -196,11 +196,17 @@ test_that("wsVal() results",{ ## Validate Results ---- -test_that("wrAdd() matches values computed in Excel.",{ +test_that("wrAdd() matches values computed 'by hand' in Excel.",{ # Read in external CSV file - ftmp <- system.file("extdata","PSDWR_testdata.csv",package="FSA") - df <- read.csv(ftmp) - - df$wr <- wrAdd(wt~tl+species,data=df) - expect_equal(df$wr,df$WR) + ftmp <- system.file("extdata","PSDWR_data4testthat.csv",package="FSA") + tmp <- read.csv(ftmp) + # Create a thesaurus for a couple of species + thes <- c("Bluegill"="Bluegill Sunfish", + "Lake Trout"="Lean Lake Trout") + # Add wr variable as calculated in FSA + tmp$wr2 <- wrAdd(wt~len+species2,data=tmp, + thesaurus=thes, + WsOpts=list(Ruffe=list(ref=75))) + # Compare + expect_equal(tmp$wr,tmp$wr2) }) From aec416b0181eab64ac38661877652708757bbe28 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Tue, 25 Nov 2025 11:07:02 -0600 Subject: [PATCH 10/16] Updating testthat for PSD-related functions --- NEWS.md | 5 +- tests/testthat/testthat_PSD.R | 835 ++++++++++++++++++---------------- 2 files changed, 443 insertions(+), 397 deletions(-) diff --git a/NEWS.md b/NEWS.md index fa416015..05384535 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,13 +1,12 @@ # FSA 0.10.9000 * `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. Thanks to Dave Glover. +* `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)). Also updated information info 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 `thesaurus` functionality. * `PSDWRTest`: Added for testing PSD and relative weight functions. -* `wrAdd()`: Addressed bugs similar to those for `psdAdd()`. +* `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 info 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). -* `wrAdd()`: Added `thesaurus` functionality. Reworked examples in documentation. Reworked testing framework (especially expanded validation of results with hand-calculations). * `wsVal()`: Added `thesaurus` functionality. # FSA 0.10.0 diff --git a/tests/testthat/testthat_PSD.R b/tests/testthat/testthat_PSD.R index 42f0d21f..4bc01642 100644 --- a/tests/testthat/testthat_PSD.R +++ b/tests/testthat/testthat_PSD.R @@ -1,280 +1,295 @@ -## Data for tests -set.seed(56768) -df <- data.frame(tl=round(c(rnorm(100,mean=125,sd=15), - rnorm(50,mean=200,sd=25), - rnorm(20,mean=300,sd=40)),0), - species=factor(rep("Yellow Perch",170))) - -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) - -# read in external CSV file -ftmp <- system.file("extdata", "PSDWR_testdata.csv", package="FSA") +## Preparation +#===== Read in external CSV file for validation (near end) +ftmp <- system.file("extdata", "PSDWR_data4testthat.csv", package="FSA") df2 <- read.csv(ftmp) -df2$species <- factor(df2$species) -df2$spec_code <- factor(df2$spec_code) -df2$GCATN <- factor(df2$GCATN,levels=c("substock","stock","quality","preferred", - "memorable","trophy")) -df2bg <- droplevels(subset(df2,species=="Bluegill")) -df2lmb <- droplevels(subset(df2,species=="Largemouth Bass")) - +df2$psd <- factor(df2$psd,levels=c("substock","stock","quality","preferred", + "memorable","trophy")) +thes <- c("Bluegill"="Bluegill Sunfish","Lake Trout"="Lean Lake Trout") ## Test Messages ---- test_that("psdVal() messages",{ - ## bad species name + #===== bad species name expect_error(psdVal("Derek"), "There are no Gablehouse lengths in 'PSDlit'") expect_error(psdVal("bluegill"), "There are no Gablehouse lengths in 'PSDlit'") - ## too many species name + + #===== too many species name expect_error(psdVal(c("Bluegill","Yellow Perch")), "can have only one name") - ## needed and bad group= + + #===== needed and bad group= expect_error(psdVal("Brown Trout"), "\"Brown Trout\" has Gabelhouse categories for these") expect_error(psdVal("Brown Trout",group="Derek"), "There is no \"Derek\" group for \"Brown Trout\"") - ## bad units + expect_error(psdVal("Brown Trout (Lotic)"), + "There are no Gablehouse lengths in \'PSDlit\'") + + #===== bad units expect_error(psdVal("Bluegill",units="inches"), "should be one of") - ## addLens and addNames don't match up + + #===== addLens and addNames don't match up expect_error(psdVal("Bluegill",addLens=7,addNames=c("Derek","Ogle")), - "have different lengths") + "\'addLens\' and \'addNames\' have different lengths") expect_error(psdVal("Bluegill",addLens=c(7,9),addNames="Derek"), - "have different lengths") - ## and addLens is also a Gabelhouse length + "\'addLens\' and \'addNames\' have different lengths") + + #===== and addLens is also a Gabelhouse length expect_warning(psdVal("Bluegill",addLens=150), "The following Gabelhouse length categories were removed") }) -test_that("psdCI() messages",{ - ## problems with proportions table - # not obviously a proportions table - # expect_warning(psdCI(c(1,0,0,0),c(0.5,0.3,0.2,10),11)) - # expect_warning(psdCI(c(1,0,0,0),c(5,3,2,10),20)) - # looks like proportions, but doesn't sum to 1 - expect_error(psdCI(c(1,0,0,0),c(0.5,0.3,0.1,0.08),20), - "does not sum to 1") - expect_error(psdCI(c(1,0,0,0),c(0.5,0.3,0.2,0.08),20), - "does not sum to 1") - # small n for table using multinomial distribution - expect_warning(psdCI(c(0,0,0,1),c(0.5,0.3,0.1,0.1),20,method="multinomial"), - "CI coverage may be lower than 95%") +test_that("psdAdd() messages",{ + #===== Get some data for multiple species + df <- subset(PSDWRtest, + species %in% c("Yellow Perch","Iowa Darter", + "Bluegill Sunfish","Brown Trout"), + select=c("species","len","wt")) - ## problems with indicator vector - ipsd <- c(0.130,0.491,0.253,0.123) - n <- 445 - # all zeros - expect_error(psdCI(c(0,0,0,0),ipsd,n), - "cannot be all zeros") - # all ones - expect_error(psdCI(c(1,1,1,1),ipsd,n), - "cannot be all ones") - # wrong length of indvec - expect_error(psdCI(c(1,0,0),ipsd,n), - "must be the same") - expect_error(psdCI(c(1,0,0,0,0),ipsd,n), - "must be the same") + #===== bad variable types + expect_error(psdAdd(species~len,df), + "Variable on left-hand-side of \'len\' is not numeric") + expect_error(psdAdd(len~wt,df), + "\'len\' must have one and only one factor") + expect_error(psdAdd(df$species,df$len), + "\'len\' must be numeric") + expect_error(psdAdd(df$len,df$wt), + "\'species\' must be character or factor") - ## ptbl not proportions - ipsd <- c(5,4,3,3) - n <- 300 - expect_warning(psdCI(c(1,0,0,0),ipsd,n), - "not a table of proportions") + #===== bad formulae + expect_error(psdAdd(~len,df), + "\'len\' must have one variable on the left-hand-side") + expect_error(psdAdd(~species,df), + "\'len\' must have one variable on the left-hand-side") + expect_error(psdAdd(len~wt+species,df), + "\'len\' must have one variable on the left-hand-side") - # bad args in conf.level - ipsd <- c(0.130,0.491,0.253,0.123) - n <- 445 - expect_error(psdCI(c(0,0,1,1),ipsd,n=n,conf.level=0), - "must be between 0 and 1") - expect_error(psdCI(c(0,0,1,1),ipsd,n=n,conf.level=1), - "must be between 0 and 1") - expect_error(psdCI(c(0,0,1,1),ipsd,n=n,conf.level="R"), - "must be numeric") + #===== Sub-group and thesaurus issues (and messages about no lengths) + psdAdd(len~species,data=df) %>% + expect_message("Species in the data with no Gabelhouse") %>% + expect_error("\"Brown Trout\" has Gabelhouse categories for these") + tmp <- psdAdd(len~species,data=df,group=list("Brown Trout"="lotic")) %>% + expect_message("Species in the data with no Gabelhouse") + tmp <- psdAdd(len~species,data=df,group=list("Brown Trout"="lotic"), + thesaurus=c("bluegill"="Bluegill Sunfish")) %>% + expect_message("The following species names were in \'thesaurus\'") %>% + expect_message("Species in the data with no Gabelhouse") + psdAdd(len~species,data=df,group=list("Brown Trout"="lotic"), + thesaurus=c("Bluegill Sunfish")) %>% + expect_error("Values in \'thesaurus\' must be named") + psdAdd(len~species,data=df,group=list("Brown Trout"="lotic"), + thesaurus=c("Bluegill"=7)) %>% + expect_error("Values in \'thesaurus\' must be strings") + psdAdd(len~species,data=df,group=list("Brown Trout"="lotic"), + thesaurus=c("Bluegill"=factor("Bluegill Sunfish"))) %>% + expect_error("\'thesaurus\' must be either a vector or list") + tmp <- psdAdd(len~species,data=df,group=list("Brown Trout"="lotic"), + thesaurus=c("Bluegill"="Bluegill Sunfish")) %>% + expect_message("Species in the data with no Gabelhouse") %>% + expect_no_error() + #===== bad units + expect_error(psdAdd(len~species,df,units="inches"), + "should be one of") + expect_error(psdAdd(df$len,df$species,units="inches"), + "should be one of") + #===== One species had all missing lengths + tmp <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len")) + tmp$len <- NA_real_ + expect_message(psdAdd(len~species,tmp), + "All values in \'len\' were missing for Yellow Perch") }) test_that("psdCalc() messages",{ - ## species name does not exist in PSDlit - expect_error(psdCalc(~tl,data=df,species="Slimy Sculpin"), + #===== Get some data for one species + df <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len")) + #===== get Gabelhouse lengths for Yellow Perch + ghl <- psdVal("Yellow Perch") + + #===== species name does not exist in PSDlit + expect_error(psdCalc(~len,data=df,species="Slimy Sculpin"), "There are no Gablehouse lengths in 'PSDlit'") - expect_error(psdCalc(~tl,data=df,species="Yellow perch"), + expect_error(psdCalc(~len,data=df,species="Yellow perch"), "There are no Gablehouse lengths in 'PSDlit'") - ## needed and bad group= - expect_error(psdCalc(~tl,data=df,species="Brown Trout"), + + #===== needed and bad group= + expect_error(psdCalc(~len,data=df,species="Brown Trout"), "\"Brown Trout\" has Gabelhouse categories for these") - expect_error(psdCalc(~tl,data=df,species="Brown Trout",group="Derek"), + expect_error(psdCalc(~len,data=df,species="Brown Trout",group="Derek"), "There is no \"Derek\" group for \"Brown Trout\"") - expect_no_failure(psdCalc(~tl,data=df,species="Brown Trout",group="lotic")) %>% - suppressWarnings() + expect_error(psdCalc(~len,data=df,species="Brown Trout (Lotic)"), + "There are no Gablehouse lengths in 'PSDlit'") + psdCalc(~len,data=df,species="Brown Trout",group="lotic") %>% + expect_warning("some CI coverage may be lower") %>% + expect_no_failure() - ## get Gabelhouse lengths for Yellow Perch - ghl <- psdVal("Yellow Perch") - ## restrict data.frame to no fish - tmp <- subset(df,tl=quality fish - tmp <- subset(df,tl% - expect_warning("No fish in larger than 'stock' categories") %>% - suppressWarnings() - - ## bad formulae - expect_error(psdCalc(tl,data=df,species="Yellow Perch"), - "not found") - expect_error(psdCalc(tl~species,data=df,species="Yellow Perch"), + "\'data\' does not contain any rows") + #----- restrict data.frame to sub-stock-length fish + tmp <- subset(df,len=quality fish + tmp <- subset(df,len% + expect_warning("\'ptbl\' not a table of proportions") %>% + expect_error("\'x\' must be whole numbers") + expect_warning(psdCI(c(1,0,0,0),c(5,3,2,10),20), + "\'ptbl\' not a table of proportions") + expect_warning(psdCI(c(1,0,0,0),c(5,4,3,3),300), + "\'ptbl\' not a table of proportions") + #----- looks like proportions, but doesn't sum to 1 + expect_error(psdCI(c(1,0,0,0),c(0.5,0.3,0.1,0.08),20), + "\'ptbl\' does not sum to 1") + expect_error(psdCI(c(1,0,0,0),c(0.5,0.3,0.2,0.08),20), + "\'ptbl\' does not sum to 1") + #----- small n for table using multinomial distribution + expect_warning(psdCI(c(0,0,0,1),c(0.5,0.3,0.1,0.1),20,method="multinomial"), + "CI coverage may be lower than") + + #===== problems with indicator vector + ipsd <- c(0.130,0.491,0.253,0.123) + n <- 445 + + #----- all zeros + expect_error(psdCI(c(0,0,0,0),ipsd,n), + "\'indvec\' cannot be all zeros") + #----- all ones + expect_error(psdCI(c(1,1,1,1),ipsd,n), + "\'indvec\' cannot be all ones") + #----- wrong length of indvec + expect_error(psdCI(c(1,0,0),ipsd,n), + "Length of \'ptbl\' and \'indvec\' must be the same") + expect_error(psdCI(c(1,0,0,0,0),ipsd,n), + "Length of \'ptbl\' and \'indvec\' must be the same") + + #===== bad args in conf.level + expect_error(psdCI(c(0,0,1,1),ipsd,n=n,conf.level=0), + "\'conf.level\' must be between 0 and 1") + expect_error(psdCI(c(0,0,1,1),ipsd,n=n,conf.level=1), + "\'conf.level\' must be between 0 and 1") + expect_error(psdCI(c(0,0,1,1),ipsd,n=n,conf.level="R"), + "\'conf.level\' must be numeric") +}) + test_that("psdPlot() messages",{ - ## get Gabelhouse lengths for Yellow Perch + #===== Get some data for one species + df <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len")) + #===== get Gabelhouse lengths for Yellow Perch ghl <- psdVal("Yellow Perch") - - ## restrict data.frame to no fish - tmp <- subset(df,tl=quality fish - tmp <- subset(df,tl=130)) - tmp <- suppressWarnings(psdCalc(~tl,data=df1,species="Yellow Perch")) + + #===== All values, but df only has values greater than stock values + df1 <- droplevels(subset(df,len>=130)) + tmp <- suppressWarnings(psdCalc(~len,data=df1,species="Yellow Perch")) expect_equal(class(tmp),c("matrix","array")) expect_equal(mode(tmp),"numeric") - expect_equal(nrow(tmp),8) + expect_equal(nrow(tmp),7) expect_equal(ncol(tmp),3) - expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M","PSD-T","PSD S-Q", - "PSD Q-P","PSD P-M","PSD M-T")) + expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M", + "PSD S-Q","PSD Q-P","PSD P-M","PSD M-T")) expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) - ## All values, but df only has values greater than quality values - df1 <- droplevels(subset(df,tl>=200)) - tmp <- suppressWarnings(psdCalc(~tl,data=df1,species="Yellow Perch")) + + #===== All values, but df only has values greater than quality values + df1 <- droplevels(subset(df,len>=200)) + tmp <- suppressWarnings(psdCalc(~len,data=df1,species="Yellow Perch")) expect_equal(class(tmp),c("matrix","array")) expect_equal(mode(tmp),"numeric") - expect_equal(nrow(tmp),7) + expect_equal(nrow(tmp),6) expect_equal(ncol(tmp),3) - expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M","PSD-T", + expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M", "PSD Q-P","PSD P-M","PSD M-T")) expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) - ## All values, but df only has values greater than memorable value - df1 <- droplevels(subset(df,tl>=300)) - tmp <- suppressWarnings(psdCalc(~tl,data=df1,species="Yellow Perch")) + + #===== All values, but df only has values greater than memorable value + df1 <- droplevels(subset(df,len>=300)) + tmp <- suppressWarnings(psdCalc(~len,data=df1,species="Yellow Perch")) expect_equal(class(tmp),c("matrix","array")) expect_equal(mode(tmp),"numeric") - expect_equal(nrow(tmp),5) + expect_equal(nrow(tmp),4) expect_equal(ncol(tmp),3) - expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M","PSD-T","PSD M-T")) + expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M","PSD M-T")) expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) - ## Pretend like no species is given - tmp <- suppressWarnings(psdCalc(~tl,data=df, + #===== Pretend like no species is given + tmp <- suppressWarnings(psdCalc(~len,data=df, addLens=c("stock"=130,"quality"=200,"preferred"=250, "memorable"=300,"trophy"=380))) expect_equal(class(tmp),c("matrix","array")) expect_equal(mode(tmp),"numeric") - expect_equal(nrow(tmp),8) + expect_equal(nrow(tmp),7) expect_equal(ncol(tmp),3) - expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M","PSD-T","PSD S-Q", - "PSD Q-P","PSD P-M","PSD M-T")) + expect_equal(rownames(tmp),c("PSD-Q","PSD-P","PSD-M", + "PSD S-Q","PSD Q-P","PSD P-M","PSD M-T")) expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) - tmp <- suppressWarnings(psdCalc(~tl,data=df, + tmp <- suppressWarnings(psdCalc(~len,data=df, addLens=c("stock"=130,"name1"=200,"name2"=250))) expect_equal(class(tmp),c("matrix","array")) expect_equal(mode(tmp),"numeric") @@ -490,7 +476,7 @@ test_that("psdCalc() returns",{ expect_equal(rownames(tmp),c("PSD-name1","PSD-name2","PSD S-name1","PSD name1-name2")) expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) - tmp <- suppressWarnings(psdCalc(~tl,data=df, + tmp <- suppressWarnings(psdCalc(~len,data=df, addLens=c("stock"=130,"name1"=200))) expect_equal(class(tmp),c("matrix","array")) expect_equal(mode(tmp),"numeric") @@ -500,26 +486,80 @@ test_that("psdCalc() returns",{ expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) }) -test_that("psdAdd() returns",{ - tmp <- df - tmp$PSD <- suppressMessages(psdAdd(tl~species,data=tmp)) - expect_equal(ncol(tmp),4) - expect_true(is.factor(tmp$PSD)) - tmp$PSD <- suppressMessages(psdAdd(tl~species,data=tmp,use.names=FALSE)) - expect_equal(ncol(tmp),4) - expect_true(is.numeric(tmp$PSD)) -}) +test_that("psdCI() returns",{ + #===== Make an incremental proportions table + n <- 997 + ipsd <- c(130,491,253,123)/n + + #===== single binomial + tmp <- psdCI(c(0,0,1,1),ipsd,n=n) + expect_equal(class(tmp),c("matrix","array")) + expect_equal(mode(tmp),"numeric") + expect_equal(nrow(tmp),1) + expect_equal(ncol(tmp),3) + expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) + + tmp <- psdCI(c(1,0,0,0),ipsd,n=n,label="PSD S-Q") + expect_equal(class(tmp),c("matrix","array")) + expect_equal(mode(tmp),"numeric") + expect_equal(nrow(tmp),1) + expect_equal(ncol(tmp),3) + expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) + expect_equal(rownames(tmp),"PSD S-Q") + + #===== single multinomial + tmp <- psdCI(c(0,0,1,1),ipsd,n=n,method="multinomial") + expect_equal(class(tmp),c("matrix","array")) + expect_equal(mode(tmp),"numeric") + expect_equal(nrow(tmp),1) + expect_equal(ncol(tmp),3) + expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) + + tmp <- psdCI(c(1,0,0,0),ipsd,n=n,method="multinomial",label="PSD S-Q") + expect_equal(class(tmp),c("matrix","array")) + expect_equal(mode(tmp),"numeric") + expect_equal(nrow(tmp),1) + expect_equal(ncol(tmp),3) + expect_equal(colnames(tmp),c("Estimate","95% LCI","95% UCI")) + expect_equal(rownames(tmp),"PSD S-Q") + + #===== Adjustment for not proportions + ipsd <- c(130,491,253,123) + n <- sum(ipsd) + ipsd2 <- ipsd/n + + tmp <- suppressWarnings(psdCI(c(0,0,1,1),ipsd,n=n)) + tmp2 <- psdCI(c(0,0,1,1),ipsd2,n=n) + expect_equal(tmp,tmp2) + + tmp <- suppressWarnings(psdCI(c(0,0,1,1),ipsd,n=n,method="multinomial")) + tmp2 <- psdCI(c(0,0,1,1),ipsd2,n=n,method="multinomial") + expect_equal(tmp,tmp2) + + ## Adjustment for a PSD of 0 or 1 + ipsd <- c(1,0,0,0) + n <- 455 + tmp <- psdCI(c(1,1,0,0),ipsd,n=n) + expect_equal(tmp,matrix(c(100,NA,NA),nrow=1),ignore_attr=TRUE) + + ipsd <- c(0,0,0,1) + n <- 455 + tmp <- psdCI(c(1,1,0,0),ipsd,n=n) + expect_equal(tmp,matrix(c(0,NA,NA),nrow=1),ignore_attr=TRUE) +}) ## Validate Results ---- test_that("Does psdAdd() create correct Gabelhouse categories?",{ - suppressMessages(df2$gcatn <- psdAdd(tl~species,data=df2)) - expect_equal(df2$gcatn,df2$GCATN) + #!!!!! df2 has hand-calculated results for psd variable + suppressMessages(df2$psd2 <- psdAdd(len~species2,data=df2, + thesaurus=thes)) + expect_equal(df2$psd,df2$psd2) }) test_that("Does psdAdd() properly handle NA in species?",{ - ## Makes sure NAs are in proper position and by extension correct number - # Just NAs for species only one other species + #!!!!! Makes sure NAs are in proper position and by extension correct number + #===== Just NAs for species only one other species testdf <- data.frame(TL=c(400,90,250,130,50), Spp=c("White Crappie",NA,"White Crappie", "White Crappie","White Crappie")) @@ -527,7 +567,7 @@ test_that("Does psdAdd() properly handle NA in species?",{ expect_equal(which(is.na(testdf$TL) | is.na(testdf$Spp)), which(is.na(gcat))) - # Just NAs for species only multiple other species + #===== Just NAs for species only multiple other species testdf <- data.frame(TL=c(400,90,250,130,50), Spp=c("White Crappie",NA,"White Crappie", "White Crappie","Black Crappie")) @@ -535,7 +575,7 @@ test_that("Does psdAdd() properly handle NA in species?",{ expect_equal(which(is.na(testdf$TL) | is.na(testdf$Spp)), which(is.na(gcat))) - # Just NAs for species, but with a species w/o Gabelhouse lengths + #===== Just NAs for species, but with a species w/o Gabelhouse lengths testdf <- data.frame(TL=c(400,90,250,NA,50), Spp=c("White Crappie",NA,"badSpp", "White Crappie","Black Crappie")) @@ -543,139 +583,118 @@ test_that("Does psdAdd() properly handle NA in species?",{ expect_equal(which(is.na(testdf$TL) | is.na(testdf$Spp) | testdf$Spp=="badSpp"), which(is.na(gcat))) - # NAs for length and species + #===== NAs for length and species testdf <- data.frame(TL=c(400,90,250,NA,50), Spp=c("White Crappie",NA,"White Crappie", "White Crappie","Black Crappie")) suppressMessages(gcat <- psdAdd(TL~Spp,data=testdf,drop.levels=TRUE)) expect_equal(which(is.na(testdf$TL) | is.na(testdf$Spp)), which(is.na(gcat))) - }) test_that("Does psdCalc() compute correct PSD values?",{ - suppressWarnings(bgres <- psdCalc(~tl,data=df2bg,species="Bluegill")) - expect_equal(bgres[,"Estimate"],c(80,60,40,20,20,20,20,20),ignore_attr=TRUE) - suppressWarnings(lmbres <- psdCalc(~tl,data=df2lmb,species="Largemouth Bass")) - expect_equal(lmbres[,"Estimate"],c(60,30,10,40,30,20,10),ignore_attr=TRUE) - ## pretend like no species is given (but using bluegill results) - suppressWarnings(bgres <- psdCalc(~tl,data=df2bg, - addLens=c("stock"=80,"quality"=150, - "preferred"=200,"memorable"=250, - "trophy"=300))) - expect_equal(bgres[,"Estimate"],c(80,60,40,20,20,20,20,20),ignore_attr=TRUE) + #===== Bluegill and Bass examples + suppressWarnings(res <- psdCalc(~len,data=subset(df2,species=="Bluegill Sunfish"), + species="Bluegill")) + expect_equal(res[,"Estimate"],c(55,10,45,45,10),ignore_attr=TRUE) + suppressWarnings(res <- psdCalc(~len,data=subset(df2,species=="Largemouth Bass"), + species="Largemouth Bass")) + expect_equal(res[,"Estimate"],c(43,4,57,39,4),ignore_attr=TRUE) + + #===== pretend like no species is given (but using bluegill results) + suppressWarnings(res <- psdCalc(~len,data=subset(df2,species=="Bluegill Sunfish"), + species="Bluegill", + addLens=c("stock"=80,"quality"=150, + "preferred"=200,"memorable"=250, + "trophy"=300))) + expect_equal(res[,"Estimate"],c(55,10,45,45,10),ignore_attr=TRUE) }) #test_that("Does psdCalc() work with a tibble?",{ -# tmp <- tibble::as_tibble(df2bg) -# suppressWarnings(bgres <- psdCalc(~tl,data=df2bg,species="Bluegill")) -# suppressWarnings(bgres2 <- psdCalc(~tl,data=tmp,species="Bluegill")) -# expect_equal(bgres,bgres2) +# #!!!!! Commented out so as not to have to include tibble in package depends +# tmp1 <- subset(df2,species=="Bluegill Sunfish") +# tmp2 <- tibble::as_tibble(tmp1) +# suppressWarnings(res1 <- psdCalc(~len,data=tmp1,species="Bluegill")) +# suppressWarnings(res2 <- psdCalc(~len,data=tmp2,species="Bluegill")) +# expect_equal(res,res2) #}) -test_that("Does psdCI results match Brenden et al. (2008) results",{ - ## proportions table from Brenden et al. (2008) - ipsd <- c(0.130,0.491,0.253,0.123) - n <- 445 - - ## results from Brendent et al. (2008) ... Table 2 - bpsd <- cbind(c(13,49,25,12,87,38), - c(9,42,20,8,82,31), - c(17,56,31,17,91,44)) - colnames(bpsd) <- c("Estimate","95% LCI","95% UCI") - rownames(bpsd) <- c("PSD S-Q","PSD Q-P","PSD P-M","PSD M-T","PSD","PSD-P") - - ## psdCI calculations - imat <- matrix(c(1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1, - 0,1,1,1, - 0,0,1,1),nrow=6,byrow=TRUE) - rownames(imat) <- rownames(bpsd) - mcis <- t(apply(imat,MARGIN=1,FUN=psdCI,ptbl=ipsd,n=n,method="multinomial")) - colnames(mcis) <- c("Estimate","95% LCI","95% UCI") - diff <- mcis-bpsd - # Brenden's results were rounded, thus all should be within 0.5 - expect_true(all(abs(diff)<=0.5)) -}) - -test_that("Does psdCI results match Brenden et al. (2008) results",{ - ## Setup sample with known PSD values +test_that("Does psdCalc() results match Brenden et al. (2008) results",{ + #===== Setup sample with known PSD values brks <- psdVal("Yellow Perch") freq <- c(110,75,50,35,20,10) - df3 <- data.frame(tl=rep(brks,freq)+sample(1:45,300,replace=TRUE), + tmp <- data.frame(tl=rep(brks,freq)+sample(1:45,300,replace=TRUE), species=factor(rep("Yellow Perch",300))) - ## Get known PSD values + + #===== Get known PSD values psdXYs <- prop.table(freq[-1])*100 psdXs <- rcumsum(psdXYs)[-1] psdXYs <- psdXYs[-length(psdXYs)] - ## Get psdCalc results + + #----- Get psdCalc results suppressWarnings( - resXY <- psdCalc(~tl,data=df3,species="Yellow Perch",what="incremental", + resXY <- psdCalc(~tl,data=tmp,species="Yellow Perch",what="incremental", digits=getOption("digits"))) suppressWarnings( - resX <- psdCalc(~tl,data=df3,species="Yellow Perch",what="traditional", + resX <- psdCalc(~tl,data=tmp,species="Yellow Perch",what="traditional", digits=getOption("digits"))) - ## Are lengths what you would expect + + #----- Are lengths what you would expect expect_equal(nrow(resXY),4) expect_equal(nrow(resX),4) - ## Are values the same + #----- Are values the same diffs <- round(resXY[,"Estimate"]-psdXYs,7) expect_equal(diffs,rep(0,length(diffs)),ignore_attr=TRUE) diffs <- round(resX[,"Estimate"]-psdXs,7) expect_equal(diffs,rep(0,length(diffs)),ignore_attr=TRUE) - ## Do things still work if all sub-stock fish are removed - tmp <- droplevels(subset(df3,tl>=brks["stock"])) + #===== Do things still work if all sub-stock fish are removed + tmp1 <- droplevels(subset(tmp,tl>=brks["stock"])) suppressWarnings( - resXY <- psdCalc(~tl,data=tmp,species="Yellow Perch",what="incremental", + resXY <- psdCalc(~tl,data=tmp1,species="Yellow Perch",what="incremental", digits=getOption("digits"))) suppressWarnings( - resX <- psdCalc(~tl,data=tmp,species="Yellow Perch",what="traditional", + resX <- psdCalc(~tl,data=tmp1,species="Yellow Perch",what="traditional", digits=getOption("digits"))) expect_equal(nrow(resXY),4) expect_equal(nrow(resX),4) - ## Are values the same diffs <- round(resXY[,"Estimate"]-psdXYs,7) expect_equal(diffs,rep(0,length(diffs)),ignore_attr=TRUE) diffs <- round(resX[,"Estimate"]-psdXs,7) expect_equal(diffs,rep(0,length(diffs)),ignore_attr=TRUE) - ## Do things still work if all sub-stock and stock fish are removed + #===== Do things still work if all sub-stock and stock fish are removed psdXYs <- prop.table(freq[-c(1:2)])*100 psdXs <- rcumsum(psdXYs)[-1] psdXYs <- psdXYs[-length(psdXYs)] - tmp <- droplevels(subset(df3,tl>=brks["quality"])) + tmp1 <- droplevels(subset(tmp,tl>=brks["quality"])) suppressWarnings( - resXY <- psdCalc(~tl,data=tmp,species="Yellow Perch",what="incremental", + resXY <- psdCalc(~tl,data=tmp1,species="Yellow Perch",what="incremental", digits=getOption("digits"))) suppressWarnings( - resX <- psdCalc(~tl,data=tmp,species="Yellow Perch",what="traditional", + resX <- psdCalc(~tl,data=tmp1,species="Yellow Perch",what="traditional", digits=getOption("digits"))) expect_equal(nrow(resXY),3) # no S-Q row expect_equal(nrow(resX),4) # all should be there - ## Are values the same diffs <- round(resXY[,"Estimate"]-psdXYs,7) expect_equal(diffs,rep(0,length(diffs)),ignore_attr=TRUE) diffs <- round(resX[-1,"Estimate"]-psdXs,7) expect_equal(diffs,rep(0,length(diffs)),ignore_attr=TRUE) - ## Do things still work if all trophy fish are removed + #===== Do things still work if all trophy fish are removed psdXYs <- prop.table(freq[-c(1,length(freq))])*100 psdXs <- rcumsum(psdXYs)[-1] - tmp <- droplevels(subset(df3,tl Date: Tue, 25 Nov 2025 13:57:16 -0600 Subject: [PATCH 11/16] Removed thesaurus= from psdVal() and wsVal() --- NEWS.md | 4 +-- R/psdAdd.R | 44 ++++++++++++++++++++++- R/psdCalc.R | 2 +- R/psdVal.R | 64 +++------------------------------- R/wrAdd.R | 43 +++++++++++++++++++++++ R/wsVal.R | 54 +++------------------------- man/psdAdd.Rd | 4 ++- man/psdVal.Rd | 18 +--------- man/wrAdd.Rd | 4 +++ man/wsVal.Rd | 12 +------ tests/testthat/testthat_WSWR.R | 12 ------- 11 files changed, 107 insertions(+), 154 deletions(-) diff --git a/NEWS.md b/NEWS.md index 05384535..79c2b08a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,11 +3,11 @@ * `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)). Also updated information info 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 `thesaurus` functionality. +* `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 info 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). -* `wsVal()`: Added `thesaurus` functionality. +* `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). diff --git a/R/psdAdd.R b/R/psdAdd.R index 13704696..4010c326 100644 --- a/R/psdAdd.R +++ b/R/psdAdd.R @@ -16,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}. #' @@ -252,3 +254,43 @@ psdAdd.formula <- function(len,data=NULL,thesaurus=NULL, 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 ac2129b6..18ee5674 100644 --- a/R/psdCalc.R +++ b/R/psdCalc.R @@ -107,7 +107,7 @@ psdCalc <- function(formula,data,species, #----- Make sure species is not missing, or if it is that addLens have been given if (!missing(species)) { - brks <- psdVal(species,thesaurus=NULL,group=group,units=units, + brks <- psdVal(species,group=group,units=units, incl.zero=FALSE,addLens=addLens,addNames=addNames) } else { # species is missing so must have an addLens diff --git a/R/psdVal.R b/R/psdVal.R index 62aa2287..304e7a24 100644 --- a/R/psdVal.R +++ b/R/psdVal.R @@ -3,7 +3,6 @@ #' @description Returns a vector with the five Gabelhouse lengths for a chosen species. #' #' @param species A string that contains the species name for which to find Gabelhouse lengths. See details. -#' @param thesaurus A named vector or 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 group A string that contains the sub-group of \code{species} for which to find the Gabelhouse lengths; e.g., things like \dQuote{landlocked}, \dQuote{lentic}. #' @param units A string that indicates the units for the returned lengths. Choices are \code{mm} for millimeters (DEFAULT), \code{cm} for centimeters, and \code{in} for inches. #' @param incl.zero A logical that indicates if a zero is included in the first position of the returned vector (DEFAULT) or not. This position will be named \dQuote{substock}. See details. @@ -13,11 +12,9 @@ #' @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. -#' -#' 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. #' +#' 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. @@ -72,26 +69,15 @@ #' psdVal("Bluegill",units="in",addLens=c("MinLen"=7)) #' psdVal("Bluegill",units="in",addLens=c("MinSlot"=7,"MaxSlot"=9)) #' -#' #===== Values for species in PSDlit but named differently ... use thesaurus -#' #----- Single species in thesaurus ... not that useful -#' psdVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) -#' #----- Multiple species in thesaurus (i.e., possibly a global thesaurus) -#' thes <- c("Bluegill"="Bluegill Sunfish", -#' "Rainbow Darter"="Rainbow Perch", -#' "Pumpkinseed"="Pumpkinseed Sunfish", -#' "Lake Trout"="Lean Lake Trout") -#' psdVal("Bluegill Sunfish",thesaurus=thes) -#' psdVal("Lean Lake Trout",thesaurus=thes) -#' #' @export psdVal -psdVal <- function(species="List",thesaurus=NULL, - group=NULL,units=c("mm","cm","in"), +psdVal <- function(species="List",group=NULL,units=c("mm","cm","in"), addLens=NULL,addNames=NULL, incl.zero=TRUE,showJustSource=FALSE,dat=NULL) { units <- match.arg(units) + #====== 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 <- iPrepPSDlit(thesaurus) + if (is.null(dat)) dat <- FSA::PSDlit dat <- iPSDGetSpecies(dat,species,group) #====== Prepare Result as longs as dat was not returned as NULL @@ -132,46 +118,6 @@ psdVal <- function(species="List",thesaurus=NULL, } } - -# ============================================================================== -# 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 species in dat/PSDlit 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 -} - # ============================================================================== # Internal -- check species name against the 'dat' data.frame (usually PSDLit) # ============================================================================== diff --git a/R/wrAdd.R b/R/wrAdd.R index 80ec0ce1..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. @@ -244,3 +248,42 @@ wrAdd.formula <- function(wt,data,thesaurus=NULL,units=c("metric","English"),... wrAdd.default(tmp$mf[,tmp$Rpos],tmp$mf[,tmp$ENumPos], 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 4b888a24..dba9b5e2 100644 --- a/R/wsVal.R +++ b/R/wsVal.R @@ -10,20 +10,17 @@ #' #' 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. #' -#' 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} 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. -#' @param thesaurus A named vector or list for providing alternative species names (the values in the list) that correspond to specific names in \code{WSlit} (the names in the list). See details and examples. #' @param group A string that contains the sub-group of \code{species} for which to find the Ws coefficients; e.g., things like \dQuote{lotic}, \dQuote{lentic}, \dQuote{female}, \dQuote{male}. #' @param units A string that indicates whether the coefficients for the standard weight equation to be returned are in \code{"metric"} (DEFAULT; mm and g) or \code{"English"} (in and lbs) units. #' @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{psdAdd}). +#' @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. #' @@ -61,11 +58,6 @@ #' wsVal("Brown Trout (lotic)") #' wsVal("Brown Trout (lentic)") #' -#' #===== Find equation for Bluegill Sunfish (aka Bluegill in WSlit) -#' # Note that this not that useful here as could just use "Bluegill" -#' # in first argument. This will be useful in wrAdd() -#' wsVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) -#' #' #===== Add Ws & Wr values to a data frame (for one species) ... also see wrAdd() #' #----- Example data from PSDWRtest, simplify variables for this example #' yepdf <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len","wt")) @@ -96,12 +88,12 @@ #' } #' #' @export -wsVal <- function(species="List",thesaurus=NULL,group=NULL, +wsVal <- function(species="List",group=NULL, units=c("metric","English"),ref=NULL,method=NULL, simplify=FALSE,dat=NULL) { #===== load WSlit data frame into this functions environment type <- measure <- NULL # avoiding bindings warning in RCMD CHECK - if (is.null(dat)) dat <- iPrepWSlit(thesaurus) + if (is.null(dat)) dat <- FSA::WSlit units <- match.arg(units) if (length(species)>1) STOP("'species' must contain only one name.") @@ -195,42 +187,4 @@ wsVal <- function(species="List",thesaurus=NULL,group=NULL, df <- df[,names(df) %in% c("species",tmp,"int","slope","quad")] df } -} - -# ============================================================================== -# 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 -} +} \ No newline at end of file diff --git a/man/psdAdd.Rd b/man/psdAdd.Rd index 621480eb..a8679890 100644 --- a/man/psdAdd.Rd +++ b/man/psdAdd.Rd @@ -66,7 +66,9 @@ Creates a vector of the Gabelhouse lengths specific to a species for all individ \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}. diff --git a/man/psdVal.Rd b/man/psdVal.Rd index 3a4b58a4..dd6fad11 100644 --- a/man/psdVal.Rd +++ b/man/psdVal.Rd @@ -6,7 +6,6 @@ \usage{ psdVal( species = "List", - thesaurus = NULL, group = NULL, units = c("mm", "cm", "in"), addLens = NULL, @@ -19,8 +18,6 @@ psdVal( \arguments{ \item{species}{A string that contains the species name for which to find Gabelhouse lengths. See details.} -\item{thesaurus}{A named vector or 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.} - \item{group}{A string that contains the sub-group of \code{species} for which to find the Gabelhouse lengths; e.g., things like \dQuote{landlocked}, \dQuote{lentic}.} \item{units}{A string that indicates the units for the returned lengths. Choices are \code{mm} for millimeters (DEFAULT), \code{cm} for centimeters, and \code{in} for inches.} @@ -44,9 +41,7 @@ Returns a vector with the five Gabelhouse lengths for a chosen species. \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. -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. +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. @@ -88,17 +83,6 @@ psdVal("Bluegill",units="in",addLens=c(7,9),addNames=c("MinSlot","MaxSlot")) psdVal("Bluegill",units="in",addLens=c("MinLen"=7)) psdVal("Bluegill",units="in",addLens=c("MinSlot"=7,"MaxSlot"=9)) -#===== Values for species in PSDlit but named differently ... use thesaurus -#----- Single species in thesaurus ... not that useful -psdVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) -#----- Multiple species in thesaurus (i.e., possibly a global thesaurus) -thes <- c("Bluegill"="Bluegill Sunfish", - "Rainbow Darter"="Rainbow Perch", - "Pumpkinseed"="Pumpkinseed Sunfish", - "Lake Trout"="Lean Lake Trout") -psdVal("Bluegill Sunfish",thesaurus=thes) -psdVal("Lean Lake Trout",thesaurus=thes) - } \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. diff --git a/man/wrAdd.Rd b/man/wrAdd.Rd index f8dc4ffb..df416899 100644 --- a/man/wrAdd.Rd +++ b/man/wrAdd.Rd @@ -48,6 +48,10 @@ This computes a vector that contains the relative weight specific to each specie 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. diff --git a/man/wsVal.Rd b/man/wsVal.Rd index f8dab386..70fd1966 100644 --- a/man/wsVal.Rd +++ b/man/wsVal.Rd @@ -6,7 +6,6 @@ \usage{ wsVal( species = "List", - thesaurus = NULL, group = NULL, units = c("metric", "English"), ref = NULL, @@ -18,8 +17,6 @@ wsVal( \arguments{ \item{species}{A string that contains the species name for which to find Ws coefficients. See details.} -\item{thesaurus}{A named vector or list for providing alternative species names (the values in the list) that correspond to specific names in \code{WSlit} (the names in the list). See details and examples.} - \item{group}{A string that contains the sub-group of \code{species} for which to find the Ws coefficients; e.g., things like \dQuote{lotic}, \dQuote{lentic}, \dQuote{female}, \dQuote{male}.} \item{units}{A string that indicates whether the coefficients for the standard weight equation to be returned are in \code{"metric"} (DEFAULT; mm and g) or \code{"English"} (in and lbs) units.} @@ -30,7 +27,7 @@ wsVal( \item{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.} -\item{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{psdAdd}).} +\item{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}).} } \value{ 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. @@ -49,8 +46,6 @@ See \code{\link{WSlit}} for more information about the meaning of each value ret 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. -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} 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. @@ -81,11 +76,6 @@ wsVal("Brown Trout",group="lentic") wsVal("Brown Trout (lotic)") wsVal("Brown Trout (lentic)") -#===== Find equation for Bluegill Sunfish (aka Bluegill in WSlit) -# Note that this not that useful here as could just use "Bluegill" -# in first argument. This will be useful in wrAdd() -wsVal("Bluegill Sunfish",thesaurus=c("Bluegill"="Bluegill Sunfish")) - #===== Add Ws & Wr values to a data frame (for one species) ... also see wrAdd() #----- Example data from PSDWRtest, simplify variables for this example yepdf <- subset(PSDWRtest,species=="Yellow Perch",select=c("species","len","wt")) diff --git a/tests/testthat/testthat_WSWR.R b/tests/testthat/testthat_WSWR.R index ebe4a5ca..cc3fd2d4 100644 --- a/tests/testthat/testthat_WSWR.R +++ b/tests/testthat/testthat_WSWR.R @@ -48,18 +48,6 @@ test_that("wsVal() messages",{ "Ws equations exist for both the RLP and EmP") expect_error(wsVal("Arctic Grayling",method="Derek"), "There is no Ws equation for \"Arctic Grayling\" derived") - #===== bad thesaurus - expect_error(wsVal("Bluegill Sunfish"), - "There is no Ws equation in \'WSlit\' for \"Bluegill Sunfish\"") - expect_error(wsVal("Bluegill Sunfish",thesaurus=c("Bluegill")), - "Values in \'thesaurus\' must be named") - expect_error(wsVal("Bluegill Sunfish",thesaurus=c("Bluegill"=7)), - "Values in \'thesaurus\' must be strings of species names") - expect_error(wsVal("Bluegill Sunfish",thesaurus=factor(c("Bluegill"="Bluegill Sunfish"))), - "\'thesaurus\' must be either a vector or list") - wsVal("Bluegill Sunfish",thesaurus=c("bluegill"="Bluegill Sunfish")) %>% - expect_message("The following species names were in \'thesaurus\' but do not") %>% - expect_error("There is no Ws equation in \'WSlit\' for \"Bluegill Sunfish\"") }) test_that("wrAdd() messages",{ From f03cc3e722174dc22540b226acba8be1a485500c Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Sat, 29 Nov 2025 16:42:55 -0600 Subject: [PATCH 12/16] Updated PSD and Wr articles --- NEWS.md | 1 + data-raw/WSlit.csv | 4 +- data/WSlit.rdata | Bin 6029 -> 6025 bytes vignettes/articles/Computing_PSDs.qmd | 231 +++++++++++++----- .../articles/Computing_Relative_Weights.qmd | 200 ++++++++++----- 5 files changed, 315 insertions(+), 121 deletions(-) diff --git a/NEWS.md b/NEWS.md index 79c2b08a..04fd6649 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,5 @@ # FSA 0.10.9000 +* 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. diff --git a/data-raw/WSlit.csv b/data-raw/WSlit.csv index 035eaeba..384f6ed7 100644 --- a/data-raw/WSlit.csv +++ b/data-raw/WSlit.csv @@ -221,8 +221,8 @@ Spotted Sunfish,NA,TL,English,75,EmP,2.75,8,-3.3468,3.3343,NA,Bonvechio et al. ( 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 -Spriped 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 -Spriped 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 (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 diff --git a/data/WSlit.rdata b/data/WSlit.rdata index b762b180ec5358785bdd4f6ba528cd41d15f9a3d..fea00364aa0ab6723bcc105615355c13d0ec8d14 100644 GIT binary patch delta 4787 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 N{6Dj{Pu9Dn005HS%EABu delta 4791 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 RL*RY<^Z&=eMKQXh0010p+sgm| diff --git a/vignettes/articles/Computing_PSDs.qmd b/vignettes/articles/Computing_PSDs.qmd index b814153a..2c0191ce 100644 --- a/vignettes/articles/Computing_PSDs.qmd +++ b/vignettes/articles/Computing_PSDs.qmd @@ -29,7 +29,7 @@ library(dplyr) # mutate, select, group_by, summarize ``` -# Creating PSD-Related Length Categories +# Looking-Up PSD-Related Lengths ## Gabelhouse Length Categories Five-cell Gabelhouse (GH) length categories have been deveoped for a number of freshwater game fish in the United States, as well as several non-game fish in the United States and some other fish from outside of the United States. These values have been collated into the `PSDlit` data.frame^[Specifics [here](https://fishr-core-team.github.io/FSA/reference/PSDlit.html).] distributed with `FSA` and are most easily accessed with `psdVal()`. For example, the GH length categories for Bluegill are retrieved below. @@ -71,12 +71,36 @@ A small number of species have separate length designations for sub-groups of th psdVal("Brown Trout") ``` -Then try again with `group=` as suggested to select a specific group. +Then try again with `group=` to select a specific group as suggested. ```{r} psdVal("Brown Trout",group="lotic") ``` +These same species and sub-group combinations can also be accessed by combining the species name and lower-case sub-group name (in parenthesis) into the first argument (and then not using `group=`). + +```{r} +psdVal("Brown Trout (lotic)") +``` + +Thus, species with sub-group designations can be identified by scanning the list of names returned by `psdVal()` for parentheses. This has some limitations as there are a few species that appear to have a sub-group but the name with parentheses is only used here (in `PSDlit`) to facilitate use when calculating PSD and relative weight metrics^[As described in [this vignette](https://fishr-core-team.github.io/FSA/articles/Computing_Relative_Weights.html).] with the same data.frame. Muskellunge is an example of this where there is only one set of GH length categories but they are repeated for separate sub-groups because separate standard weight equations exist for these sub-groups. + +```{r} +psdVal("Muskellunge") +psdVal("Muskellunge (overall)") +psdVal("Muskellunge (female)") +psdVal("Muskellunge (male)") +``` + +There are also a few species where an original definition of GH length categories has been revised in the literature. The original and revised definitions are available in `PSDlit` with the revised definitions accessed by using just the species name and the original definitions accessed by appending "(original)" to the species name. + +```{r} +psdVal("Spotted Bass") # revised definitions +psdVal("Spotted Bass (original)") +``` + +We strongly urge you to have a good understanding of the GH length categories for your species' of interest and make sure that `psdVal()` is returning the values that you expect (i.e., correct species, sub-group (if appropriate), units, etc.). + ## Additional Length Categories There may be times when you desire length categories in addition to the GH lengths. For example, suppose that the minimum length limit for Largemouth Bass is 254 mm. This length can be included as one of the categories by including a vector with the length (or lengths) to `addLens=`. If the item in the vector is named (second example below) then the value will also be named in the returned result. @@ -91,9 +115,9 @@ Multiple additional lengths can be included. psdVal("Largemouth Bass",addLens=c("minSlot"=254,"maxSlot"=356)) ``` -# Adding Length Category Variable for One Species +# Add Length Categories for One Species ## "Manual" Additions -Suppose that we want to add another variable with the GH length categories to the data.frame of lengths (along with capture location) for Yellow Perch from Saginaw Bay, MI in `YPerchSB1` (distributed with the `FSAdata` package). Note here that lengths are in **centimeters**. +Suppose that we want to add a variable with the GH length categories to the data.frame of lengths (along with capture location) for Yellow Perch from Saginaw Bay, MI in `YPerchSB1` (distributed with the `FSAdata` package). Note here that lengths are in **centimeters**. ```{r} data(YPerchSB1,package="FSAdata") @@ -122,55 +146,158 @@ YPerchSB1 <- YPerchSB1 |> peek(YPerchSB1,n=10) ``` -A frequency table can then be used to find the number of individuals in each category. +## Use the `psdAdd()` Convenience Function +`psdAdd()` can be used to add a length categorization variable to a data.frame for **all** species in the data.frame for which the GH length categories exists.^[Here, however, it is being applied to a data.frame with only one species.] The main argument to `psdAdd()` is a formula of the form `length~species`, where `length` is the observed length variable and `species` is the name of the species variable. In these data there is no variable that identified the species, likely because the data contains only one species. Thus, before `psdAdd()` can be used in this example, a new variable with the species name was added.^[`YperchSB1` was loaded again to start without the modifications performed previously.] + +```{r} +data(YPerchSB1,package="FSAdata") +YPerchSB1 <- YPerchSB1 |> + mutate(species="Yellow Perch", + ghcats1=psdAdd(tl~species,units="cm")) +peek(YPerchSB1,n=10) +``` + +`psdAdd()` requires that the species variable have the species names in the spelling and capitalization used by `PSDlit`. So, for example, suppose that the `YPerchSB1` species names used the abbreviation `yep` rather than `Yellow Perch`.^[Note that `YPerchSB1` is loaded again to start over and the new abbreviation is added for this example.] A named list or vector can be given to `thesaurus=` that defines how the original species names (i.e., the values in the vector) relate to the species names required by `PSDlit` (i.e., the names in the vector). `psdAdd()` will match the two names appropriately while creating the GH length categories. ```{r} -xtabs(~ghcats2,data=YPerchSB1) +data(YPerchSB1,package="FSAdata") +YPerchSB1 <- YPerchSB1 |> + mutate(species="yep", + ghcats1=psdAdd(tl~species,units="cm",thesaurus=c("Yellow Perch"="yep"))) +peek(YPerchSB1,n=10) ``` -The reverse cumulative sum of these values, with the substock fish removed, divided by the stock-length sum times 100 are the PSD-X values. +# Add Length Categories for Multiple Species +The real value of `psdAdd()` is that it can be used to efficiently add length categories for multiple species in a single data.frame. This is illustrated below with examples for a variety of scenarios. + +## "Good" Names and No Groups +`InchLake2` distributed with `FSAdata` contains lengths for several species captured from Inch Lake. These data provide a simple example for using `psdAdd()` because all species names are spelled as required and none of the species have sub-groups.^[See the next section for how to deal with these issues.] Note that lengths are in **inches** here. ```{r} -( tmp <- rcumsum(xtabs(~ghcats2,data=YPerchSB1))[-1] ) -round(tmp/tmp["stock"]*100,1) +data("InchLake2",package="FSAdata") +peek(InchLake2,n=10) ``` -So, for example, `r round(tmp/tmp["stock"]*100,1)[["quality"]]`\% of fish that reach stock-size also reached quality-size (i.e., "PSD-Q"). +`psdAdd()` can be used as described previously (i.e., with a formula of the form `length~species` and `units=`) to add GH length categories for all species in the data.frame for which GH length categories exist in `PSDlit`. A message will be issued identifying the species in the data.frame for which GH length categories do not exist. The new variable will be `` for those species. + +```{r} +InchLake2 <- InchLake2 |> + mutate(ghcats1=psdAdd(length~species,units="in")) +peek(InchLake2,n=10) +``` + +Additional non-GH length categories can be used with `psdAdd()` through `addLens()` similar to what was described for `psdVal()`. However, a named list must be given to `addLens()` that has named vectors for each species for what additional lengths are added. An example for this is given in [the documentation](https://fishr-core-team.github.io/FSA/reference/psdAdd.html) for `psdAdd()`. + +## "Bad" Names and No Groups +Now consider the `Herman` data.frame (distributed with the `FSAdata` package) that has the lengths (cm) of four species -- Walleye, Yellow Perch, Black Crappie, and Black Bullhead -- from Lake Herman, SD. These four species do not have sub-groups defined in `PSDlit`. However, observing the data below^[And [the documentation](https://fishr-core-team.github.io/FSAdata/reference/Herman.html).] shows that the species variable (`spec`) contains codes for the species names rather than the names required by `PSDlit`. + +```{r} +data(Herman,package="FSAdata") +peek(Herman,n=10) +``` + +One way to deal with the issue of "bad" species names is to use a named list or vector that defines how the names from `PSDlit` should be matched to the names in the data.frame. For this purpose, the species names in `PSDlit` are the names in the vector (i.e., before the `=`) and the species names in the data.frame are the values in the vector (i.e., after the `=`). + +```{r} +thes <- c("Walleye"="wae","Yellow Perch"="yep", + "Black Crappie"="bkc","Black Bullhead"="bbh") +``` + +This list/vector is then given to `thesaurus=` in `psdAdd()` which will perform the name matching while creating the GH length categories. + +```{r} +Herman <- Herman |> + mutate(ghcats1=psdAdd(tl~spec,units="cm",thesaurus=thes)) +peek(Herman,n=10) +``` + +`thesaurus=` can be used even if only some of the species names are non-"standard." Additionally, the named list/vector in `thesaurus=` can contain names that don't exist in the original data.frame. Thus, a global thesaurus containing all species that *could* be encountered could be created, for example as an agency-wide definition, and used with a variety of specific data.frames. + +## "Bad" Names and Groups +The use of `psdAdd()` can become complicated for data.frames with species names other than what `PSDlit` expects and species for which GH lengths exist for sub-groups, especially if more than one sub-group is in the data. The hypothetical data set `PSDWRtest` distributed with `FSA` can be used to illustrate how to handle these "issues". + +```{r} +peek(PSDWRtest,n=20) +``` + +`psdAdd()` will produce some informative error messages, but it is best that you have a full understanding of the issues that may arise with your data by carefully examining your data and understanding the GH length categories for the species in your data. The "issues" that need to be addressed with the `PSDWRtest` data are as follows: + + - "Bluegill Sunfish" was used rather than "Bluegill". + - "Lean Lake Trout" was used rather than "Lake Trout". + - Brook Trout were sampled from a lotic ("Trout Lake") system, for which there are sub-groups for GH length categories. + - Brown Trout were sampled from a lotic ("Trout Lake") and lentic ("Brush Creek") system, for which there are sub-groups for GH length categories. + +The easiest way to deal with all of these "issues" is to create a new "species" variable (i.e., `species2` below) that appends the specific groups in parentheses to the species name. There are a variety of ways to do this and which way (is best or works) may depend on the specifics of the situation. Here, we primarily use `case_when()` from `dplyr` with a series of statements that begin with a "condition" to the left of the `~` and a new species "name" for that condition to the right of the `~`. The `.default=species` at the end will put the name from `species` into `species2` for all situations where none of the conditions above it are met (e.g., if `species` is "Yellow Perch" then `species2` will be "Yellow Perch"). + +```{r} +PSDWRtest <- PSDWRtest |> + mutate(species2=case_when( + species=="Bluegill Sunfish" ~ "Bluegill", + species=="Lean Lake Trout" ~ "Lake Trout", + species=="Brown Trout" & location=="Trout Lake" ~ "Brown Trout (lotic)", + species=="Brown Trout" & location=="Brushy Creek" ~ "Brown Trout (lentic)", + species=="Brook Trout" & location=="Trout Lake" ~ "Brook Trout (lotic)", + .default=species + )) +peek(PSDWRtest,n=20) +``` + +The GH length categories are added to this data.frame with `psdAdd()`, specifically noting the use of the new `species2` variable. + +```{r} +PSDWRtest$psd <- psdAdd(len~species2,data=PSDWRtest) +peek(PSDWRtest,n=20) +``` + +Handling these types of "issues" in conjunction with computing relative weights is illustrated in the companion [XXXX](). -## Use the `psdAdd()` Convenience Function -`psdAdd()` can be used to add a length categorization variable to a data.frame for **all** species in the data.frame for which the GH length categories exists. The main argument to `psdAdd()` is a formula of the form `length~species`, where `length` is the observed length variable and `species` is the name of the species variable. Again, the species must be spelled (and capitalized) as in `PSDlit`. In these data there is no variable that identified the species, likely because the data contains only one species. Thus, for this example, before `psdAdd()` can be used, a new variable with the species name must be added. + + +# Computing PSD Summaries +## For One Species from Length Category Variable +PSD summaries for a single species from the GH length category variable will be illustrated with the `YPerchSB1` data.frame created above. ```{r} +data(YPerchSB1,package="FSAdata") YPerchSB1 <- YPerchSB1 |> mutate(species="Yellow Perch", - ghcats3=psdAdd(tl~species,units="cm")) + ghcats1=psdAdd(tl~species,units="cm")) peek(YPerchSB1,n=10) ``` -The PSD-X metrics can then be computed as before. +A frequency table is used to find the number of individuals in each category. The substock-sized fish are immediately dropped (if they are present). ```{r} -( tmp <- rcumsum(xtabs(~ghcats3,data=YPerchSB1))[-1] ) -round(tmp/tmp["stock"]*100,1) +( tmp <- xtabs(~ghcats1,data=YPerchSB1) ) +( tmp <- tmp[-1] ) ``` -# Using `psdCalc()` to Compute All PSD-X and PSD-X-Y Values for One Species -All of that (in the previous sections) is a bit tedious and, more importantly, does not compute confidence intervals for the values.^[See `psdCI()` for how to compute confidence intervals from the raw data.] `psdCalc()` provides a convenient interface for computing all of the PSD metrics, with confidence intervals, for a data.frame with one species. Before illustrating `psdCalc()`, I returned to the original `YPerchSB1` data.frame without the changes made in the previous sections. +The PSD X-Y (i.e., incremental PSD) values are computed by dividing each value in the frequency table that excludes the sub-stock fish by the sum of that frequency table multiplied by 100, which is easily accomplished with `prop.table()`. ```{r} -#| echo: false -data(YPerchSB1,package="FSAdata") +( tmp <- prop.table(tmp)*100 ) ``` + +Thus, for example, `r round(tmp[["stock"]])`\% of fish that reached stock-size were between stock- and quality-sized (i.e,. "PSD S-Q"). + +The PSD-X (i.e., traditional PSD) values are computed by the reverse cumulative sum (i.e., accumulating from right-to-left) on the `prop.table()` results (and dropping the results for the stock-sized fish which will always by 1). + ```{r} -peek(YPerchSB1,n=6) +( tmp <- rcumsum(tmp)[-1] ) ``` + +So, for example, `r round(tmp[["quality"]],1)`\% of fish that reach stock-size also reached quality-size (i.e., "PSD-Q"). + +## Using `psdCalc()` for One Species +The calculations in the previous section are a bit tedious and, more importantly, do not compute confidence intervals for the values.^[See `psdCI()` for how to compute confidence intervals from the raw data.] `psdCalc()` provides a convenient interface for computing all of the PSD metrics, with confidence intervals, for a data.frame with **one** species. + ```{r} #| echo: false #| results: hide ypres <- psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm") ``` -`psdCalc()` takes a formula of the form `~length` as the first argument with the appropriate data.frame in `data=`. As with `psdVal()`, `psdCalc()` requires the correctly spelled (and capitalized) species name in `species=` and units in `units=`.^[Again, `units=` defaults to `mm`.] +`psdCalc()` takes a formula of the form `~length` as the first argument with the appropriate data.frame in `data=`. As with `psdVal()`, `psdCalc()` requires the correctly spelled (and capitalized) species name in `species=` and units in `units=`.^[Again, `units=` defaults to `mm`.] Note in the use below that the GH length category variable is not needed (thus, the calculations below do **not** need to follow `psdAdd()`). ```{r} psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm") @@ -182,7 +309,7 @@ By default, PSD metrics that are 0 are dropped from the results. They can be inc psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm",drop0Est=FALSE) ``` -The PSD-X (in contrast to PSD X-Y) values are referred to here as "traditional" PSD metrics as they show the percent of stock-sized fish that were also X-sized. For example, PSD-P is the percent of stock-sized fish that also reach preferred-size. In this example, `r ypres["PSD-P","Estimate"]`\% (95%CI: `r ypres["PSD-P","95% LCI"]`\%-`r ypres["PSD-P","95% UCI"]`\%) of stock-sized fish attained preferred size. +The PSD-X (in contrast to PSD X-Y) values are referred to here as "traditional" PSD metrics as they show the percent of stock-sized fish that were also X-sized. For example, PSD-P is the percent of stock-sized fish that also reached preferred-size. In this example, `r ypres["PSD-P","Estimate"]`\% (95%CI: `r ypres["PSD-P","95% LCI"]`\%-`r ypres["PSD-P","95% UCI"]`\%) of stock-sized fish attained preferred size. Just the "traditional" metrics may be returned by including `what="traditional"`. @@ -214,42 +341,17 @@ psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm", addLens=c("minSlot"=17.5,"maxSlot"=27.5)) ``` -## Using `psdPlot()` to Visualize the PSD Metrics -`psdPlot()` can be used to produce a histogram of lengths with different colors for substock- and stock-size fish, vertical lines depicting the GH length categories, and the "traditional" PSD metrics shown. The basic arguments to `psdPlot()` are the same as those to `psdCalc()`. - -```{r} -#| fig-width: 5 -#| fig-height: 4.5 -psdPlot(~tl,data=YPerchSB1,species="Yellow Perch",units="cm") -``` - -There may be times where the length category lines don't fall on the breaks for the histogram bars. You may be able to ameliorate this issue by changing the width of the breaks with `w=` or where the breaks start with `startcat=`.^[While this was not an issue with these data, this code shows how to make narrower bar widths with `w=`.] - -```{r} -#| fig-width: 5 -#| fig-height: 4.5 -psdPlot(~tl,data=YPerchSB1,species="Yellow Perch",units="cm",w=0.5) -``` - -This plot is meant to be illustrative and not of "publication-quality." However, some aspects of the plot can be modified to make some changes in appearance. See `?psdPlot` for documentation of these other arguments. - -# Adding a Length Category Variable for All Species -The real value of `psdAdd()` is that it can be used to efficiently add length categories for multiple species in a single data.frame. For example, `InchLake2` distributed with `FSAdata` contains lengths for several species captured from Inch Lake. Note that lengths are in **inches** here. +## For Multiple Species from Length Category Variable +PSD-X and PSD X-Y summaries for multiple species requires more work as will be demonstrated below with the `InchLake2` data.frame from previous. ```{r} data("InchLake2",package="FSAdata") -peek(InchLake2,n=10) -``` - -`psdAdd()` can be used as described previously (i.e., with a formula of the form `length~species` and `units=`) to add GH length categories for all species in the data.frame for which GH length categories exist in `PSDlit`. Note that a message will be issued identifying the species in the data.frame for which GH length categories do not exist. The new variable will be `NA` for these species. - -```{r} InchLake2 <- InchLake2 |> mutate(ghcats1=psdAdd(length~species,units="in")) peek(InchLake2,n=10) ``` -Summaries by species requires some work. First, remove all substock-sized individuals. +First, remove all substock-sized individuals. ```{r} Inch_mod <- InchLake2 |> @@ -257,23 +359,21 @@ Inch_mod <- InchLake2 |> droplevels() ``` -Incremental PSD metrics (i.e, PSD X-Y) are quickly computed with `xtabs()` and `prop.table()`. +Incremental PSD metrics (i.e, PSD X-Y) are then computed with `xtabs()` and `prop.table()`, similar to before except that `margin=` must be used in `prop.table()` so that the proportions are computed from the row totals. ```{r} -freq <- xtabs(~species+ghcats1,data=Inch_mod) +( freq <- xtabs(~species+ghcats1,data=Inch_mod) ) iPSDs <- prop.table(freq,margin=1)*100 round(iPSDs,1) ``` -Traditional PSD metrics (i.e., PSD-X) can be found by `apply()`ing `rcumsum()`^[This finds reverse cumulative sums; i.e., sums from end-to-start, rather than start-to-end.] to each row (i.e., `MARGIN=1`) of the PSD X-Y values. The result from `apply()` will be oriented opposite of what is desired (i.e., species a columns rather than rows), so it should be `t()`ransposed. +Traditional PSD metrics (i.e., PSD-X) are found by `apply()`ing `rcumsum()`^[This finds reverse cumulative sums; i.e., sums from end-to-start, rather than start-to-end.] to each row (i.e., `MARGIN=1`) of the PSD X-Y values. The result from `apply()` will be oriented opposite of what is desired (i.e., species in columns rather than rows), so it should be `t()`ransposed. ```{r} tPSDs <- t(apply(iPSDs,MARGIN=1,FUN=rcumsum)) round(tPSDs,1) ``` -Additional non-GH length categories can be used with `psdAdd()` through `addLens()` similar to what was described for `psdVal()` and `psdCalc()`. However, a named list must be given to `addLens()` that as named vectors for each species for what an additional length is added. An example for this is given in the documentation for `psdAdd()`. - The use of `psdAdd()` is fairly efficient if interest is only in the point PSD-X or PSD X-Y values. If one needs confidence intervals for these values then it is probably best to use `psdCalc()` on separate data.frames for each species. This is demonstrated below for Yellow Perch and Bluegill from the Inch Lake data. ```{r} @@ -281,9 +381,26 @@ InchYP <- InchLake2 |> filter(species=="Yellow Perch") psdCalc(~length,data=InchYP,species="Yellow Perch",units="in") ``` - ```{r} InchBG <- InchLake2 |> filter(species=="Bluegill") psdCalc(~length,data=InchBG,species="Bluegill",units="in") ``` +## Using `psdPlot()` to Visualize the PSD Metrics +`psdPlot()` can be used to produce a histogram of lengths with different colors for substock- and stock-size fish, vertical lines depicting the GH length categories, and the "traditional" PSD metrics shown. The basic arguments to `psdPlot()` are the same as those to `psdCalc()`. + +```{r} +#| fig-width: 5 +#| fig-height: 4.5 +psdPlot(~tl,data=YPerchSB1,species="Yellow Perch",units="cm") +``` + +There may be times where the length category lines don't fall on the breaks for the histogram bars. You may be able to ameliorate this issue by changing the width of the breaks with `w=` or where the breaks start with `startcat=`.^[While this was not an issue with these data, this code shows how to make narrower bar widths with `w=`.] + +```{r} +#| fig-width: 5 +#| fig-height: 4.5 +psdPlot(~tl,data=YPerchSB1,species="Yellow Perch",units="cm",w=0.5) +``` + +This plot is meant to be illustrative and not of "publication-quality." However, some aspects of the plot can be modified to make some changes in appearance. See `?psdPlot` for documentation of these other arguments. diff --git a/vignettes/articles/Computing_Relative_Weights.qmd b/vignettes/articles/Computing_Relative_Weights.qmd index 430a5abf..e8ff7fe5 100644 --- a/vignettes/articles/Computing_Relative_Weights.qmd +++ b/vignettes/articles/Computing_Relative_Weights.qmd @@ -33,7 +33,7 @@ library(dplyr) # mutate, select, group_by, summarize ``` -# Standard Weight Equations +# Looking Up Standard Weight Equations Equations for computing the standard weight (i.e., $Ws_i$) from an individual fish's observed length (i.e., $L_i$) have been derived for a number of freshwater game fish in the United States, as well as several non-game fish in the United States and some other fish from outside of the United States. The specifics of these equations have been collated into the `WSlit` data.frame^[Specifics [here](https://fishr-core-team.github.io/FSA/reference/WSlit.html).] distributed with `FSA` and are most easily accessed with `wsVal()`. For example, the specifics of the standard weight equation for Bluegill are retrieved below. ```{r} @@ -48,7 +48,7 @@ The results returned from `wsVal()` are: - `units`: the units for which the equation was developed. The default is `metric` which has length in mm and weight in grams. However, `English` can also be used which has lengths in inches and weight in pounds. These are the only two "units" for which the equation can be returned; thus, if you recorded lengths and weights in different units you will need to adjust your data accordingly (or adjust the standard weights computed from the equations (see below) accordingly). - `ref`: the quantile used when developing the standard weight equation. The 75th percentile is used for most species, but some species have alternatives (50th or 25th percentile). Alternatives for a species can be chosen with `ref=` in `wsVal()`.^[For species with only one possible `ref`, then `ref=` should be left at the default `NULL`.] - `method`: the method used to develop the standard weight equation. This will usually be `RLP` (regression-line-percentile) or `EmP` (empirical percentile) but is `Other` only for Bluegill, as shown here. Some (very few) species have equations for both methods. In these instances, you will need to choose which to use with `method=` in `wsVal()`.^[For species where only one method is available then leave `method=` at the default `NULL`.] -- `min.TL`: the minimum length for which the standard weight equation is appropriate.^[The postfix after the period will be replaced with the `measure` type ( (here `TL` but for some species `FL`, `BL`, or `CL`)).] +- `min.TL`: the minimum length for which the standard weight equation is appropriate.^[The postfix after the period will be replaced with the `measure` type (here `TL` but for some species `FL`, `BL`, or `CL`).] - `max.TL`: the maximum length for which the standard weight equation is appropriate. Maximum lengths have not been specified for all species and, thus, may not appear in all outputs (e.g., for Bluegill here). - `int`: the intercept, **on the common logarithm (i.e., log10) scale**, for the standard weight equation. - `slope`: the slope, **on the log10 scale**, for the standard weight equation. @@ -82,7 +82,7 @@ wsVal("Blue sucker") wsVal("Blue suckr") ``` -It is also not always obvious whether a species has equations for sub-groups or not.^[But see @tbl-species_issues.] One way to deal with this is to just ask for the equation for your species of interest without using `group=`. If sub-groups exist then you will get an error message asking you to choose which sub-group to use. +It is also not always obvious whether a species has equations for sub-groups or not. One way to deal with this is to just ask for the equation for your species of interest without using `group=`. If sub-groups exist then you will get an error message asking you to choose which sub-group to use. ```{r} #| error: true @@ -95,7 +95,13 @@ Then try again by choosing the sub-group with `group=`. wsVal("Brown Trout",group="lentic") ``` -The same general process can be used for species that have equations developed from multiple methods. +These same species and sub-group combinations can be also accessed by combining the species name and sub-group name (in parenthesis) into the first argument (and then not using `group=`). + +```{r} +wsVal("Brown Trout (lotic)") +``` + +The same general process can be used for species that have equations developed from multiple methods; though, only the sub-group identifiers can be combined (with parentheses) in the species name and used in the first argument. ```{r} #| error: true @@ -111,41 +117,33 @@ wsVal("Ruffe") wsVal("Ruffe",ref=50) ``` -## Cautions -@tbl-species_issues shows species for which multiple standard weight equations exist in `WSlit` such that the specific one must be chosen by using `group=`, `method=`, or `ref=` in `wsVal()`. +There are two species (Chinook Salmon and Striped Bass) that appear to have sub-groups (i.e., "landlocked") but only that one specific sub-group appears in `WSlit`. The standard weight literature for these species did not identify the equation as only being for "landlocked" populations. However, these entries were added to facilitate use when calculating proportional size distribution (PSD) metrics,^[See [this vignette]().] which were defined just for "landlocked" populations, and relative weight metrics with the same data.frame.^[As illustrated in [this companion vignette().] The standard weight equations for these species can be accessed by either just the species name or the species name with the group in parentheses. However, note that they are the exact same information. +```{r} +wsVal("Striped Bass") +wsVal("Striped Bass (landlocked)") +``` -| Species | Cause of Multiple Equations | -|:-----|:--------------------| -| Arctic Grayling | Multiple `method`s exist | -| Bigmouth Sleepers | Sub-`group`s exist; multiple `ref`erence values | -| Brook Trout | Sub-`group`s exist | -| Brown Trout | Sub-`group`s exist | -| Cutthroat Trout | Sub-`group`s exist | -| Mountain Mullet | Multiple `ref`erence values | -| Muskellunge | Sub-`group`s exist | -| Paddlefish | Sub-`group`s exist | -| Rainbow Trout | Sub-`group`s exist | -| River Goby | Multiple `ref`erence values | -| Ruffe | Multiple `ref`erence values | -| Sardine | Multiple `ref`erence values | -| Spotted Bass | Sub-`group`s exist | -| Walleye | Sub-`group`s exist | +There are also a few species where an original standard weight equation has been revised in the literature. The original and revised equations are available in `WSlit` with the revised equations accessed by just using the species name and the original equations accessed by appending "(original)" to the species name. -: Species for which the user will have to select among multiple standard weight equations by using `group=`, `method=`, or `ref=` in `wsVal()`. {#tbl-species_issues} +```{r} +wsVal("Spotted Bass") # revised definitions +wsVal("Spotted Bass (original)") +``` +We strongly urge you to have a good understanding of the standard weight literature for your species' of interest and make sure that `wsVal()` is returning the values that you expect. # Calculate Individual Relative Weight -## Example with Linear Equation -The specifics of the standard weight equation returned by `wsVal()` can be used to compute the standard weight for a fish given its observed length. As an example, suppose that the relative weight of a Largemouth Bass with an observed length and weight of 350 mm and 650 g is desired. +## For Typical Linear Equation +The specifics of the standard weight equation returned by `wsVal()` can be used to compute the standard weight for a fish given its observed length. As an example, suppose that the relative weight of a Largemouth Bass with an observed length of 350 mm and weight of 650 g is desired. Begin by assigning the specifics of the standard weight equation for Largemouth Bass returned by `wsVal()` to an object (e.g., `wsLMB` here). ```{r} -wsLMB <- wsVal("Largemouth Bass") +( wsLMB <- wsVal("Largemouth Bass") ) ``` -The intercept and slope for the standard weight equation on the **log10-log10** scale can be extracted from this object. +The intercept and slope for the standard weight equation on the **log10-log10** scale can be extracted from this object.^[The double-brackets (i.e., `[[]]`) are used to remove the name (e.g., `int`) from the returned value.] ```{r} wsLMB[["int"]] @@ -158,16 +156,16 @@ The standard weight is then computed from these results and the **log10-transfor ( ex1 <- 10^(wsLMB[["int"]]+wsLMB[["slope"]]*log10(350)) ) ``` -This calculation suggests that standard weight for a 250 mm Largemouth Bass is `r formatC(ex1,format="f",digits=1)` g. With this and @eq-Wri, the relative weight for this individual can be computed (recalling that the observed weight was 650 g). +This calculation suggests that the standard weight for a 350 mm Largemouth Bass is `r formatC(ex1,format="f",digits=1)` g. With this and @eq-Wri, the relative weight for this individual is computed (recalling that the observed weight was 650 g). ```{r} 100*650/ex1 ``` -This indicates that the individual is heavier than a standard fish of the same length as this values is greater than 100. +This indicates that the individual is (slightly) heavier than a standard fish of the same length as this values is greater than 100. -## Example with Quadratic Equation -A similar process can be followed for species where the standard weight equation includes a quadratic term. The only "trick" here is to include the quadratic term multiplied by the **square** of the log10-transformed observed length when computing the standard weight. This calculation is illustrated below with a 500 mm and 1010 g Blue Sucker. +## For Quadratic Equation +A similar process can be followed for a species where the standard weight equation includes a quadratic term. The only "trick" here is to include the quadratic term multiplied by the **square** of the log10-transformed observed length when computing the standard weight. This calculation is illustrated below with a 500 mm and 1010 g Blue Sucker. ```{r} ( wsBS <- wsVal("Blue Sucker",simplify=TRUE) ) @@ -186,16 +184,13 @@ A few things to consider when calculating relative weights for individuals. # Calculate Relative Weights for All of One Species It is not common to compute the standard and relative weights for a single individual as was done in the previous section. Rather, it is more useful to calculate these values for all individuals in a sample, and then summarize those values for an overall assessment of the condition of those individuals. -Consider the `CiscoTL` data.frame distributed with the `FSAdata` package that contains the lengths (mm) and weights (g) of Cisco (*Coregonus artedii*) sampled from Trout Lake, WI, USA over a 25 year period. +Consider the `CiscoTL` data.frame distributed with the `FSAdata` package that contains the lengths (mm) and weights (g) of Cisco (*Coregonus artedii*) sampled from Trout Lake, WI, USA over a 25 year period. Note that there are lots of missing weights in this data.frame. ```{r} data("CiscoTL",package="FSAdata") -str(CiscoTL) peek(CiscoTL,n=10) ``` -Note that there are lots of missing weights in this data.frame. - ## "Manual" Calculations The relative weight calculation begins by finding the specifics of the standard weight equation for Cisco. @@ -203,7 +198,7 @@ The relative weight calculation begins by finding the specifics of the standard ( wsC <- wsVal("Cisco") ) ``` -Two new variables -- `Ws` for standard weight and `Wr` for relative weight -- are added to the data.frame in three steps below. First, `Ws` is calculated using the coefficients from the standard weight equation and the log-transformed length variable as shown above (but within `mutate()` from `dplyr`). Second, if the observed length is less than the minimum length for which the standard weight equation should be applied, then the previously calculated `Ws` is replaced with an `NA` (for missing value). Finally, the relative weight is computed from the observed weight and standard weight variables using @eq-Wri. +Two new variables -- `Ws` for standard weight and `Wr` for relative weight -- are added to the data.frame in three steps below. First, `Ws` is calculated using the coefficients from the standard weight equation and the log-transformed length variable as shown above (but within `mutate()` from `dplyr`). Second, if the observed length is less than the minimum length for which the standard weight equation should be applied, then the previously calculated `Ws` is replaced with an `NA` (for missing value).^[These two steps could have been combined by replacing `Ws` with the calculation in `ifelse()`.] Finally, the relative weight is computed from the observed weight and standard weight variables using @eq-Wri. ```{r} CiscoTL <- CiscoTL |> @@ -213,38 +208,30 @@ CiscoTL <- CiscoTL |> peek(CiscoTL,n=10) ``` -As an illustration, the mean and standard deviation of relative weights are computed below (along with `validn` which is the number of non-`NA` (i.e., non-missing) relative weights).^[More interesting summaries and plots may be constructed with these data. This is just an example of summarizing relative weights for a sample.] These results suggest that this population of Cisco is substantially "skinnier" (i.e., under-weight) than the standard for the species (because the mean relative weight is substantially less than 100). - -```{r} -CiscoTL |> - summarize(validn=sum(!is.na(Wr)), - mnWr=mean(Wr,na.rm=TRUE), - sdWr=sd(Wr,na.rm=TRUE)) -``` - ## Using the `WrAdd()` Convenience Function -`wrAdd()` can be used to add a relative weight variable to a data.frame for **all** species in the data.frame for which a standard weight equation exists. The main argument to `wrAdd()` is a formula of the form `weight~length+species` where `weight` is the observed weight variable, `length` is the observed length variable, and `species` is the name of the species variable. One constraint here is that the species must be spelled (and capitalized) as in `WSlit`. In these data for Cisco, the species name is in `spname` but the species is all capital letters as "CISCO", rather than the required "Cisco". `capFirst()`^[From `FSA`.] may be used to convert a word to a form where just the first letter is capitalized, and is used below.^[Note that the `CiscoTL` data.frame was re-read so that the additions in the previous section were removed.] +`wrAdd()` can be used to add a relative weight variable to a data.frame for **all** species in the data.frame for which a standard weight equation exists.^[Though its use is illustrated here on a data.frame with only one species. See the next sections for an example with more species.] The main argument to `wrAdd()` is a formula of the form `weight~length+species` where `weight` is the observed weight variable, `length` is the observed length variable, and `species` is the name of the species variable. One constraint here is that the names in `species` must be spelled (and capitalized) exactly as in `WSlit`. In these data, the species name is in `spname` but is in all capital letters as "CISCO", rather than the required "Cisco". `capFirst()`^[From `FSA`.] may be used to convert a word to a form where just the first letter is capitalized, and is used below.^[Note that the `CiscoTL` data.frame was re-read so that the additions in the previous section were removed.] ```{r} -#| echo: false data("CiscoTL",package="FSAdata") -``` -```{r} CiscoTL <- CiscoTL |> mutate(Wr=wrAdd(weight~length+capFirst(spname))) peek(CiscoTL,n=10) ``` -`wrAdd()` deals with species that have more than one standard weight equation^[As illustrated previuosly.] with `WsOpts=`. For example, consider adding a relative weight variable to the `RuffeSLRH92` data.frame distributed with `FSAdata`. +A more general approach to deal with species that are spelled differently than expected in `WSlit` is to provide a named list or vector that defines how the original species names (i.e., the values in the vector) relate to the species names required by `WSlit` (i.e., the names in the vector) to `thesaurus=`. `wrAdd()` will match the two names appropriately while creating the relative weight variable. ```{r} -data("RuffeSLRH92",package="FSAdata") -str(RuffeSLRH92) +CiscoTL <- CiscoTL |> + mutate(Wr2=wrAdd(weight~length+spname,thesaurus=c("Cisco"="CISCO"))) +peek(CiscoTL,n=10) ``` -Note that there is no species variable, which is needed by `wrAdd()`.^[Note that `wrAdd()` is more convenient for data.frames with multiple species as will be illustrated in the next section.] Additionally, for simplicity of presentation, I removed several other variables that are not needed for this example. +`thesaurus=` can be used even if only some of the species names are non-"standard." Additionally, the named list/vector in `thesaurus=` can contain names that don't exist in the original data.frame. Thus, a global thesaurus containing all species that *could* be encountered could be created, for example as an agency-wide definition, and used with a variety of specific data.frames. + +`wrAdd()` handles species that have more than one standard weight equation^[As described previously.] with `WsOpts=`. For example, consider adding a relative weight variable to the `RuffeSLRH92` data.frame distributed with `FSAdata`. Note that there is no species variable, which is needed by `wrAdd()`.^[Note that `wrAdd()` is more convenient for data.frames with multiple species as will be illustrated in the next section.] Additionally, for simplicity of presentation, I removed several other variables that are not needed for this example. ```{r} +data("RuffeSLRH92",package="FSAdata") RuffeSLRH92 <- RuffeSLRH92 |> mutate(species="Ruffe") |> select(species,length,weight,sex) @@ -268,29 +255,118 @@ peek(RuffeSLRH92,n=10) ``` # Calculate Relative Weights for All of Multiple Species -The real value of `wrAdd()` is that it can be used to efficiently add a relative weight variable for multiple species in a single data.frame. For example, `InchLake2` distributed with `FSAdata` contains lengths and weights for several species captured from Inch Lake. +The real value of `wrAdd()` is that it can be used to efficiently add a relative weight variable for multiple species in a single data.frame. This is illustrated below with examples for a variety of scenarios. + +## "Good" Names and No Groups +`InchLake2` distributed with `FSAdata` contains lengths and weights for several species captured from Inch Lake. These data provide a simple example for using `wrAdd()` because all species names are spelled as required and none of the species have sub-groups.^[See the next section for how to deal with these issues.] ```{r} data("InchLake2",package="FSAdata") peek(InchLake2,n=10) ``` -One oddity of these data is that length was recorded in inches, whereas weight was recorded in grams. The standard weight equations either use inches and pounds or millimeters and grams. In this case, I converted the inches to mm first, and then added the relative weight variable with `wrAdd()` as before. +A complication here is that length and weight are in "mixed" units; i.e., inches for length and grams for weight. One or the other must be converted to the same unit type. Below length is converted to mm. ```{r} InchLake2 <- InchLake2 |> - mutate(lenmm=length*25.4, - Wr=wrAdd(weight~lenmm+species)) + mutate(length=length*25.4, + Wr=wrAdd(weight~length+species)) +peek(InchLake2,n=10) +``` + +Note that species without known standard weight equations in `WSlit` (e.g., Bluntnose Minnow) will have `NA` for the relative weight variable, as will individuals with lengths outside the range of lengths for which the standard weight equation should be applied. + +## "Bad" Names and No Groups +Now consider the `BGHRfish` data.frame (distributed with the `FSAdata` package) that has the lengths (mm) and weights (g) of three species -- Smallmouth Bass, Largemouth Bass, and Bluegill -- from Big Hill Reservoir, KS. These four species do not have sub-groups defined in `WSlit`. However, observing the data below^[And [the documentation](https://fishr-core-team.github.io/FSAdata/reference/Herman.html).] shows that the species variable (`specCode`) contains codes for the species names rather than the names required by `PSDlit`. + +```{r} +data(BGHRfish,package="FSAdata") +peek(BGHRfish,n=10) +``` + +One complicating factor with these data is that `wrAdd()` expects a string in `species` rather than a numeric like `specCode`. Thus, below `specCode` will be converted to a character before using `wrAdd()`. + +One way to deal with the issue of "bad" species names is to use a named list or vector that defines how the names from `WSlit` should be matched to the names in the data.frame. For this purpose, the species names in `WSlit` are the names in the vector (i.e., before the `=`) and the species names in the data.frame are the values in the vector (i.e., after the `=`).^[The numeric species codes are in parentheses as `specCode` will be converted to a string before using `wrAdd()`.] + +```{r} +thes <- c("Smallmouth Bass"="116","Largemouth Bass"="118","Bluegill"="122") +``` + +This list/vector is then given to `thesaurus=` in `wrAdd()` which will perform the name matching while creating the GH length categories. + +```{r} +BGHRfish <- BGHRfish |> + mutate(specCode=as.character(specCode), + Wr=wrAdd(weight~length+specCode,thesaurus=thes)) +peek(BGHRfish,n=10) +``` + +## "Bad" Names, Groups, and Multiple Equations +The use of `wrAdd()` can become complicated for data.frames with species names other than what `WSlit` expects, with species for which standard weight equations exist for sub-groups, especially if more than one sub-group is in the data, and for species with multiple standard weight equations. The hypothetical data set `PSDWRtest` distributed with `FSA` can be used to illustrate how to handle these "issues". + +```{r} +peek(PSDWRtest,n=20) ``` -The mean and sd of relative weight by species is shown below. It is important to carefully examine these results because a species could have no mean relative weight calculated because there is no standard weight equation for that species (in `WSlit`) or because the species name is not spelled as expected (in `WSlit`). The four species with no mean relative weight below all do, indeed, not have a known standard weight equation. +`wrAdd()` will produce some informative error messages, but it is best that you have a full understanding of the issues that may arise with your data by carefully examining your data and understanding the standard weight (and Gabelhouse length categories) for the species in your data. The "issues" that need to be addressed with the `PSDWRtest` data are as follows: + + - "Bluegill Sunfish" was used rather than "Bluegill". + - "Lean Lake Trout" was used rather than "Lake Trout". + - Brook Trout sampled from a lotic ("Trout Lake") system, for which there are standard weight equations for sub-groups. + - Brown Trout sampled from a lotic ("Trout Lake") and lentic ("Brush Creek") system, for which there are standard weight equations for sub-groups. + - Muskellunge for which sex is known for some and not for others, and there is a desire to use the sex-specific standard weight equation when sex is known (and use the overall equation when it is not). + - Walleye of sizes for which separate standard weight equations may be used. + - Ruffe for which the reference quantile of the standard weight equation must be specified. + +The easiest way to deal with most of these "issues" is to create a new "species" variable (i.e., `species2` below) that appends the specific groups in parentheses to the species name. There are a variety of ways to do this and which way (is best or works) may depend on the specifics of the situation. Here, we primarily use `case_when()` from `dplyr` with a series of statements that begin with a "condition" to the left of the `~` and new species "name" for that condition to the right of the `~`. The `.default=species` at the end puts the name from `species` into `species2` for all situations where none of the conditions above it are met (e.g., if `species` is "Yellow Perch" then `species2` will be "Yellow Perch"). ```{r} -InchLake2 |> - group_by(species) |> +PSDWRtest <- PSDWRtest |> + mutate(species2=case_when( + species=="Bluegill Sunfish" ~ "Bluegill", + species=="Lean Lake Trout" ~ "Lake Trout", + species=="Brown Trout" & location=="Trout Lake" ~ "Brown Trout (lotic)", + species=="Brown Trout" & location=="Brushy Creek" ~ "Brown Trout (lentic)", + species=="Brook Trout" & location=="Trout Lake" ~ "Brook Trout (lotic)", + species=="Muskellunge" & sex=="M" ~ "Muskellunge (male)", + species=="Muskellunge" & sex=="F" ~ "Muskellunge (female)", + species=="Muskellunge" & sex=="U" ~ "Muskellunge (overall)", + species=="Muskellunge" & is.na(sex) ~ "Muskellunge (overall)", + species=="Walleye" & len>=150 ~ "Walleye (overall)", + species=="Walleye" & len<150 ~ "Walleye (30-149 mm)", + .default=species + )) +peek(PSDWRtest,n=20) +``` + +The relative weights for each fish (for species with standard weight equations) is added to this data.drame with `wrAdd()` as described above, noting the use of the "new" species variable `species2`. Further note the use of `wsOpts=` to define which reference quantile to use for the Ruffe standard weight equation. + +```{r} +PSDWRtest$wr <- wrAdd(wt~len+species2,data=PSDWRtest, + WsOpts=list(Ruffe=list(ref=75))) +peek(PSDWRtest,n=20) +``` + + +# Summarizing Relative Weights +## Single Species +As an illustration, the mean and standard deviation of relative weights for Cisco (in `CiscoTL` from above) are computed below (along with `validn` which is the number of non-`NA` (i.e., non-missing) relative weights).^[More interesting summaries and plots may be constructed with these data. This is just an example of summarizing relative weights for a sample.] These results suggest that this population of Cisco is substantially "skinnier" (i.e., under-weight) than the standard for the species (because the mean relative weight is substantially less than 100). + +```{r} +CiscoTL |> summarize(validn=sum(!is.na(Wr)), mnWr=mean(Wr,na.rm=TRUE), - sdWr=sd(Wr,na.rm=TRUE)) |> - as.data.frame() + sdWr=sd(Wr,na.rm=TRUE)) ``` +## Multiple Species +The mean and sd of relative weight for all species in `PSDWRtest` from above is shown below. It is important to carefully examine these results because a species could have no mean relative weight calculated because there is no standard weight equation for that species (in `WSlit`) or because the species name is not spelled as expected (in `WSlit`). The only species below with no mean relative weight (i.e., Iowa Darter) does, indeed, not have a known standard weight equation. + +```{r} +PSDWRtest |> + group_by(species,location) |> + summarize(validn=sum(!is.na(wr)), + mnWr=mean(wr,na.rm=TRUE), + sdWr=sd(wr,na.rm=TRUE)) |> + as.data.frame() +``` From a4b221798320ac7b01e78e7db36a0c707980df08 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Thu, 18 Dec 2025 08:22:57 -0600 Subject: [PATCH 13/16] Added Northern Pikeminnow to psdval and wsVal --- DESCRIPTION | 2 +- NEWS.md | 4 ++-- data-raw/PSDlit.csv | 1 + data-raw/WSlit.csv | 7 +++---- data/PSDlit.rdata | Bin 2821 -> 2857 bytes data/WSlit.rdata | Bin 6025 -> 6091 bytes 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 748e9900..26d66cb6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-12-1 +Date: 2025-12-21 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/NEWS.md b/NEWS.md index 04fd6649..2131a3c3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,11 +3,11 @@ * `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)). Also updated information info 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). +* `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 info 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). +* `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, 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 diff --git a/data-raw/PSDlit.csv b/data-raw/PSDlit.csv index 381ac7f7..48794fe8 100644 --- a/data-raw/PSDlit.csv +++ b/data-raw/PSDlit.csv @@ -48,6 +48,7 @@ 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) diff --git a/data-raw/WSlit.csv b/data-raw/WSlit.csv index 384f6ed7..4e7a8479 100644 --- a/data-raw/WSlit.csv +++ b/data-raw/WSlit.csv @@ -141,11 +141,10 @@ Nile Tilapia,NA,TL,metric,75,EmP,80,280,-8.7951,6.751,-0.8479,Emiroglu et al. (2 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),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),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 diff --git a/data/PSDlit.rdata b/data/PSDlit.rdata index 5c054ed84015a43b5e6be7ce6da2eee85c02cd80..4ffaa7a24aa803451299100274c94e7ab55186b2 100644 GIT binary patch literal 2857 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 Hku(4RR|3vj literal 2821 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 X{O7}m4}X>9KWh9Jg@b~r1vCHvYlO>l diff --git a/data/WSlit.rdata b/data/WSlit.rdata index fea00364aa0ab6723bcc105615355c13d0ec8d14..f047967a28b65176029b48a61a7f82b8e62f2de6 100644 GIT binary patch literal 6091 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 Date: Wed, 31 Dec 2025 16:16:11 -0600 Subject: [PATCH 14/16] Update to PSD and Wr vignettes --- NEWS.md | 2 +- data-raw/WSlit.csv | 11 ++-- data/WSlit.rdata | Bin 6091 -> 6078 bytes vignettes/articles/Computing_PSDs.qmd | 52 ++++++++---------- .../articles/Computing_Relative_Weights.qmd | 48 ++++++++-------- 5 files changed, 53 insertions(+), 60 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2131a3c3..debb9252 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,7 +7,7 @@ * `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, 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). +* `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 diff --git a/data-raw/WSlit.csv b/data-raw/WSlit.csv index 4e7a8479..31eb5640 100644 --- a/data-raw/WSlit.csv +++ b/data-raw/WSlit.csv @@ -3,7 +3,7 @@ Aegean Chub,NA,TL,metric,75,EmP,70,220,-3.801,1.783,0.329,Giannetto et al. (2012 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,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),min.len not made clear (assumed same as Spotted Bass); same as Spotted Bass (Alabama subspecies) +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 @@ -142,8 +142,8 @@ Nipple-Lip Scraper,NA,TL,metric,75,EmP,70,360,-5.966,3.833,-0.181,Emiroglu et al 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,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),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),Voss and Quist (2025) note that these equations are problematic and should not be used +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 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 @@ -211,9 +211,8 @@ Smallmouth Buffalo,NA,TL,metric,75,RLP,200,NA,-5.298,3.208,NA,Bister et al. (200 South European Roach,NA,TL,metric,75,EmP,60,200,-4.043,1.919,0.315,Giannetto et al. (2016),none 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),none -Spotted Bass (original),NA,TL,metric,75,RLP,100,NA,-5.392,3.215,NA,Wiens et al. (1996),none -Spotted Bass (Alabama subspecies),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 Alabama Bass +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 diff --git a/data/WSlit.rdata b/data/WSlit.rdata index f047967a28b65176029b48a61a7f82b8e62f2de6..733a0e2e070cdeb68d4a5b2eeaded718f609fb1e 100644 GIT binary patch delta 5841 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�y!2*))^lg(~qgw4XZNWW%kZ~9LAaL$-OCt_DWFj0ai2QA>4Ek`hR-2^k`r50zs1mvw~MooH#iJr_DIQ zJN1O6sgCYwt}Z3X)fzHPE2D{_b#6$-Z^+wv75u$XYw=v|jykz#nS2JR`j-#k-6D{k zJIxZLlE1R3TE+<_vx(NpTGO4qKYs(tjszshDOv_!ESRrJ%F)B*?!ft%LB&ZC#;Vg* zSbr&+V;)%Vj#`sFtG$<=pwVmh%bcpSX(vF5F^lrs5W7lP?SfS8ZqrULXtyqGMq~-Q-LI4pC1%a04&L+w1VJTT4ty2I13+C6O<8dr>bbVQ@BA5 zrIRFjouglRJ(Yabl^a5S41_G;lp*ZB+$i#Ju0OsBP5m$~H+@!`Y0ptT>2B6kbS4*M zt}CStPVy#a^dTkD8gPMz4n+6>BY!E05s=)#?1j!9SuvfF#Gx^Zi6k*MiEDJ|!eWou zDvSWG2dJtj54)t-%19^X3*A{c0X;6s0>E_%`$1BW6=Jc;_Pb)Wb*e?(*Qap%1xZYz z!l1~w+#12fFfuoq5)&zGZe(Q|^tlvnoKQg_Q$~>maY^P-8$|mCL_!IH%YO(NRK^F# zSf@ejd>MwCY`U*fE^Z*7BN*$1>r+Sq$^UbOZs)a_UA0ThCX{l7nUHNh95uhP&b-n{ z>nH!bGwVR{;J2+1*2_|GwM-> zrmBF;sLG%O(!`?p)oe=9q<MfY3;5i<7F2mcBeRq4|^nH2WiBT z%zw1Cb`^ISR=t+eVg*xYT}*%Oo#3^Iei7m#_Gg~(Gvx?ioOk*KDSu6V-(gZ`N#aZh z(b;ED9sc&!9EPix@r|&DT#|Z14B5c03H3R{s-k6dS{evhP1V<|*JLrLPn@TMA@(?* zc2~wrG;ocfaKJR2CmM}weO5weXq{giF#38~MN<=Bj^ osYp)Sbf2n>F4yG`p% - mutate(species="Yellow Perch", - ghcats1=psdAdd(tl~species,units="cm")) + mutate(spec="Yellow Perch", + ghcats1=psdAdd(tl~spec,units="cm")) peek(YPerchSB1,n=10) ``` -`psdAdd()` requires that the species variable have the species names in the spelling and capitalization used by `PSDlit`. So, for example, suppose that the `YPerchSB1` species names used the abbreviation `yep` rather than `Yellow Perch`.^[Note that `YPerchSB1` is loaded again to start over and the new abbreviation is added for this example.] A named list or vector can be given to `thesaurus=` that defines how the original species names (i.e., the values in the vector) relate to the species names required by `PSDlit` (i.e., the names in the vector). `psdAdd()` will match the two names appropriately while creating the GH length categories. +`psdAdd()` requires that the species variable have the species names in the spelling and capitalization used by `PSDlit`. So, for example, suppose that the `YPerchSB1` species names used the abbreviation `yep` rather than `Yellow Perch`.^[Note that `YPerchSB1` is loaded again to start over and the new abbreviation is added for this example.] A named list or vector can be given to `thesaurus=` that defines how the original species names (i.e., the items to the right of the `=` in the vector) relate to the species names required by `PSDlit` (i.e., the names to the left of the `=` in the vector). `psdAdd()` will match the two names appropriately while creating the GH length categories. ```{r} data(YPerchSB1,package="FSAdata") YPerchSB1 <- YPerchSB1 |> - mutate(species="yep", - ghcats1=psdAdd(tl~species,units="cm",thesaurus=c("Yellow Perch"="yep"))) + mutate(spec="yep", + ghcats1=psdAdd(tl~spec,units="cm",thesaurus=c("Yellow Perch"="yep"))) peek(YPerchSB1,n=10) ``` # Add Length Categories for Multiple Species -The real value of `psdAdd()` is that it can be used to efficiently add length categories for multiple species in a single data.frame. This is illustrated below with examples for a variety of scenarios. +The real value of `psdAdd()` is that it can be used to efficiently add length categories for multiple species in a single data.frame. This is illustrated below for a variety of scenarios. ## "Good" Names and No Groups -`InchLake2` distributed with `FSAdata` contains lengths for several species captured from Inch Lake. These data provide a simple example for using `psdAdd()` because all species names are spelled as required and none of the species have sub-groups.^[See the next section for how to deal with these issues.] Note that lengths are in **inches** here. +`InchLake2` distributed with `FSAdata` contains lengths for several species captured from Inch Lake. These data provide a simple example for using `psdAdd()` because all species names are spelled and capitalized as required (i.e., same as in `PSDlit1) and none of the species have sub-groups.^[See the next section for how to deal with these issues.] Note that lengths are in **inches** here. ```{r} -data("InchLake2",package="FSAdata") +data("InchLake2",package="FSAdata") # retrieve the data.frame peek(InchLake2,n=10) ``` -`psdAdd()` can be used as described previously (i.e., with a formula of the form `length~species` and `units=`) to add GH length categories for all species in the data.frame for which GH length categories exist in `PSDlit`. A message will be issued identifying the species in the data.frame for which GH length categories do not exist. The new variable will be `` for those species. +`psdAdd()` can be used as described previously (i.e., with a formula of the form `length~species` and `units=`) to add GH length categories for all species in the data.frame for which GH length categories exist in `PSDlit`. A message will be issued identifying the species in the data.frame for which GH length categories do not exist. The new variable will show `` for those species. ```{r} InchLake2 <- InchLake2 |> @@ -186,17 +186,17 @@ InchLake2 <- InchLake2 |> peek(InchLake2,n=10) ``` -Additional non-GH length categories can be used with `psdAdd()` through `addLens()` similar to what was described for `psdVal()`. However, a named list must be given to `addLens()` that has named vectors for each species for what additional lengths are added. An example for this is given in [the documentation](https://fishr-core-team.github.io/FSA/reference/psdAdd.html) for `psdAdd()`. +Additional non-GH length categories can be used with `psdAdd()` through `addLens()` similar to what was described for `psdVal()`. However, a named list must be given to `addLens()` that has named vectors for each species for the additional lengths to be added. An example for this is given in [the documentation](https://fishr-core-team.github.io/FSA/reference/psdAdd.html) for `psdAdd()`. ## "Bad" Names and No Groups Now consider the `Herman` data.frame (distributed with the `FSAdata` package) that has the lengths (cm) of four species -- Walleye, Yellow Perch, Black Crappie, and Black Bullhead -- from Lake Herman, SD. These four species do not have sub-groups defined in `PSDlit`. However, observing the data below^[And [the documentation](https://fishr-core-team.github.io/FSAdata/reference/Herman.html).] shows that the species variable (`spec`) contains codes for the species names rather than the names required by `PSDlit`. ```{r} -data(Herman,package="FSAdata") +data(Herman,package="FSAdata") # retrieve the data.frame peek(Herman,n=10) ``` -One way to deal with the issue of "bad" species names is to use a named list or vector that defines how the names from `PSDlit` should be matched to the names in the data.frame. For this purpose, the species names in `PSDlit` are the names in the vector (i.e., before the `=`) and the species names in the data.frame are the values in the vector (i.e., after the `=`). +One way to deal with the issue of "bad" species names is to use a named list or vector that defines how the names from `PSDlit` should be matched to the names in the data.frame. As before, the species names in `PSDlit` are the names in the vector (i.e., before the `=`) and the species names in the data.frame are the items in the vector (i.e., after the `=`). ```{r} thes <- c("Walleye"="wae","Yellow Perch"="yep", @@ -227,7 +227,7 @@ peek(PSDWRtest,n=20) - Brook Trout were sampled from a lotic ("Trout Lake") system, for which there are sub-groups for GH length categories. - Brown Trout were sampled from a lotic ("Trout Lake") and lentic ("Brush Creek") system, for which there are sub-groups for GH length categories. -The easiest way to deal with all of these "issues" is to create a new "species" variable (i.e., `species2` below) that appends the specific groups in parentheses to the species name. There are a variety of ways to do this and which way (is best or works) may depend on the specifics of the situation. Here, we primarily use `case_when()` from `dplyr` with a series of statements that begin with a "condition" to the left of the `~` and a new species "name" for that condition to the right of the `~`. The `.default=species` at the end will put the name from `species` into `species2` for all situations where none of the conditions above it are met (e.g., if `species` is "Yellow Perch" then `species2` will be "Yellow Perch"). +The easiest way to deal with all of these "issues" is to create a new "species" variable (i.e., `species2` below) that appends the specific groups in parentheses to the species name. There are a variety of ways to do this and which way (is best or works) may depend on the specifics of the situation. Here, `case_when()` from `dplyr` is used with a series of statements that begin with a "condition" to the left of the `~` and a new species "name" for that condition to the right of the `~`. The `.default=species` at the end will put the name from `species` into `species2` for all situations where none of the conditions above it are met (e.g., if `species` is "Yellow Perch" then `species2` will be "Yellow Perch"). ```{r} PSDWRtest <- PSDWRtest |> @@ -280,7 +280,7 @@ The PSD X-Y (i.e., incremental PSD) values are computed by dividing each value i Thus, for example, `r round(tmp[["stock"]])`\% of fish that reached stock-size were between stock- and quality-sized (i.e,. "PSD S-Q"). -The PSD-X (i.e., traditional PSD) values are computed by the reverse cumulative sum (i.e., accumulating from right-to-left) on the `prop.table()` results (and dropping the results for the stock-sized fish which will always by 1). +The PSD-X (i.e., traditional PSD) values are computed by the reverse cumulative sum (i.e., accumulating from right-to-left) on the `prop.table()` results (and dropping the results for the stock-sized fish which will always be 100). ```{r} ( tmp <- rcumsum(tmp)[-1] ) @@ -309,17 +309,13 @@ By default, PSD metrics that are 0 are dropped from the results. They can be inc psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm",drop0Est=FALSE) ``` -The PSD-X (in contrast to PSD X-Y) values are referred to here as "traditional" PSD metrics as they show the percent of stock-sized fish that were also X-sized. For example, PSD-P is the percent of stock-sized fish that also reached preferred-size. In this example, `r ypres["PSD-P","Estimate"]`\% (95%CI: `r ypres["PSD-P","95% LCI"]`\%-`r ypres["PSD-P","95% UCI"]`\%) of stock-sized fish attained preferred size. - -Just the "traditional" metrics may be returned by including `what="traditional"`. +The PSD-X (in contrast to PSD X-Y) values are referred to here as "traditional" PSD metrics as they show the percent of stock-sized fish that were also X-sized. For example, PSD-P is the percent of stock-sized fish that also reached preferred-size. In this example, `r ypres["PSD-P","Estimate"]`\% (95%CI: `r ypres["PSD-P","95% LCI"]`\%-`r ypres["PSD-P","95% UCI"]`\%) of stock-sized fish attained preferred size. Just the "traditional" metrics may be returned by including `what="traditional"`. ```{r} psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm",what="traditional") ``` -The PSD X-Y values are referred to here as "incremental" PSD metrics as they show the percent of stock-sized fish that were between X- and Y-sized. For example, PSD Q-P is the percent of stock-sized fish that reached quality-size but had not reach preferred-size. In this example, `r ypres["PSD Q-P","Estimate"]`\% (95%CI: `r ypres["PSD Q-P","95% LCI"]`\%-`r ypres["PSD Q-P","95% UCI"]`\%) of stock-sized fish attained quality but not preferred size. - -Just the "incremental" metrics may be returned by including `what="incremental"`. +The PSD X-Y values are referred to here as "incremental" PSD metrics as they show the percent of stock-sized fish that were between X- and Y-sized. For example, PSD Q-P is the percent of stock-sized fish that reached quality-size but had not reach preferred-size. In this example, `r ypres["PSD Q-P","Estimate"]`\% (95%CI: `r ypres["PSD Q-P","95% LCI"]`\%-`r ypres["PSD Q-P","95% UCI"]`\%) of stock-sized fish attained quality but not preferred size. Just the "incremental" metrics may be returned by including `what="incremental"`. ```{r} psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm",what="incremental") @@ -342,7 +338,7 @@ psdCalc(~tl,data=YPerchSB1,species="Yellow Perch",units="cm", ``` ## For Multiple Species from Length Category Variable -PSD-X and PSD X-Y summaries for multiple species requires more work as will be demonstrated below with the `InchLake2` data.frame from previous. +PSD-X and PSD X-Y summaries for multiple species requires more work as will be demonstrated below with the `InchLake2` data.frame from previous. Note here that `psdAdd()` is used to add the GH length categories in `ghcats1`. ```{r} data("InchLake2",package="FSAdata") @@ -359,7 +355,7 @@ Inch_mod <- InchLake2 |> droplevels() ``` -Incremental PSD metrics (i.e, PSD X-Y) are then computed with `xtabs()` and `prop.table()`, similar to before except that `margin=` must be used in `prop.table()` so that the proportions are computed from the row totals. +Incremental PSD metrics (i.e, PSD X-Y) are then computed with `xtabs()` and `prop.table()`, similar to before except that `margin=1` must be used in `prop.table()` so that the proportions are computed from the row totals. ```{r} ( freq <- xtabs(~species+ghcats1,data=Inch_mod) ) @@ -367,7 +363,7 @@ iPSDs <- prop.table(freq,margin=1)*100 round(iPSDs,1) ``` -Traditional PSD metrics (i.e., PSD-X) are found by `apply()`ing `rcumsum()`^[This finds reverse cumulative sums; i.e., sums from end-to-start, rather than start-to-end.] to each row (i.e., `MARGIN=1`) of the PSD X-Y values. The result from `apply()` will be oriented opposite of what is desired (i.e., species in columns rather than rows), so it should be `t()`ransposed. +Traditional PSD metrics (i.e., PSD-X) are found by `apply()`ing `rcumsum()`^[This finds reverse cumulative sums; i.e., sums from end-to-start, rather than start-to-end.] to each row (i.e., `MARGIN=1`) of the PSD X-Y values. The result from `apply()` will be oriented opposite of what is desired (i.e., species in columns rather than rows), so it should be transposed with `t()`. ```{r} tPSDs <- t(apply(iPSDs,MARGIN=1,FUN=rcumsum)) diff --git a/vignettes/articles/Computing_Relative_Weights.qmd b/vignettes/articles/Computing_Relative_Weights.qmd index e8ff7fe5..a7fd3aec 100644 --- a/vignettes/articles/Computing_Relative_Weights.qmd +++ b/vignettes/articles/Computing_Relative_Weights.qmd @@ -29,7 +29,7 @@ The following packages are used herein. Note that the `FSA` functions described #| results: hide #| message: false library(FSA) -library(dplyr) # mutate, select, group_by, summarize +library(dplyr) # mutate, select, group_by, summarize, case_when ``` @@ -42,12 +42,12 @@ wsVal("Bluegill") The results returned from `wsVal()` are: -- `species`: species of fish asked for. If left blank then a list of all species for which a standard weight equation exists in `WSlit` will be shown. +- `species`: species of fish asked for. - `group`: the sub-group for the species. Some species have separate standard weight equations for sub-groups (e.g,. `male` or `female`, or `lentic` and `lotic`). If `group` does not appear in the output then there is no sub-group for that species (as illustrated here). The sub-group can be chosen with `group=` in `wsVal()` as demonstrated later.^[Leave `group=` at the default `NULL` for species without sub-group equations.] -- `measure`: the length measure used (will generally be `TL` for total length, but could be `FL` for fork length, `BL` for body length, or `CL` for caudal length depending on the species). -- `units`: the units for which the equation was developed. The default is `metric` which has length in mm and weight in grams. However, `English` can also be used which has lengths in inches and weight in pounds. These are the only two "units" for which the equation can be returned; thus, if you recorded lengths and weights in different units you will need to adjust your data accordingly (or adjust the standard weights computed from the equations (see below) accordingly). -- `ref`: the quantile used when developing the standard weight equation. The 75th percentile is used for most species, but some species have alternatives (50th or 25th percentile). Alternatives for a species can be chosen with `ref=` in `wsVal()`.^[For species with only one possible `ref`, then `ref=` should be left at the default `NULL`.] -- `method`: the method used to develop the standard weight equation. This will usually be `RLP` (regression-line-percentile) or `EmP` (empirical percentile) but is `Other` only for Bluegill, as shown here. Some (very few) species have equations for both methods. In these instances, you will need to choose which to use with `method=` in `wsVal()`.^[For species where only one method is available then leave `method=` at the default `NULL`.] +- `measure`: the length measure used (will generally be `TL` for total length, but depending on the species could be `FL` for fork length, `BL` for body length, or `CL` for caudal length). +- `units`: the units for which the equation was developed. The default is `metric` which has length in mm and weight in grams. However, `English` can also be used which has lengths in inches and weight in pounds.^[A few species have an equation for only one set of units.] These are the only two "units" for which the equation can be returned; thus, if you recorded lengths and weights in different units you will need to adjust your data accordingly (or adjust the standard weights computed from the equations (see below) accordingly). +- `ref`: the quantile used when developing the standard weight equation. The 75th percentile is used for most species, but some species have alternatives (50th or 25th percentile).^[Alternatives for a species can be chosen with `ref=` in `wsVal()`. For species with only one possible `ref`, then `ref=` should be left at the default `NULL`.] +- `method`: the method used to develop the standard weight equation. This will usually be `RLP` (regression-line-percentile) or `EmP` (empirical percentile) but is `Other` only for Bluegill, as shown here. Some (very few) species have equations for both methods.^[For species with multiple `method`s, you will need to choose which to use with `method=` in `wsVal()`. For species where only one method is available then leave `method=` at the default `NULL`.] - `min.TL`: the minimum length for which the standard weight equation is appropriate.^[The postfix after the period will be replaced with the `measure` type (here `TL` but for some species `FL`, `BL`, or `CL`).] - `max.TL`: the maximum length for which the standard weight equation is appropriate. Maximum lengths have not been specified for all species and, thus, may not appear in all outputs (e.g., for Bluegill here). - `int`: the intercept, **on the common logarithm (i.e., log10) scale**, for the standard weight equation. @@ -68,7 +68,7 @@ Blue Sucker is an example where some of the "optional" values are returned (e.g. wsVal("Blue Sucker",units="English") ``` -Use of `wsVal()` requires spelling (and capitalizing) the name as it appears in `WSlit`. One can see all species names available in `WSlit` with `wsVal()` without any arguments. +Use of `wsVal()` requires spelling (and capitalizing) the species name as it appears in `WSlit`. One can see all species names available in `WSlit` with `wsVal()` without any arguments. ```{r} wsVal() @@ -117,7 +117,7 @@ wsVal("Ruffe") wsVal("Ruffe",ref=50) ``` -There are two species (Chinook Salmon and Striped Bass) that appear to have sub-groups (i.e., "landlocked") but only that one specific sub-group appears in `WSlit`. The standard weight literature for these species did not identify the equation as only being for "landlocked" populations. However, these entries were added to facilitate use when calculating proportional size distribution (PSD) metrics,^[See [this vignette]().] which were defined just for "landlocked" populations, and relative weight metrics with the same data.frame.^[As illustrated in [this companion vignette().] The standard weight equations for these species can be accessed by either just the species name or the species name with the group in parentheses. However, note that they are the exact same information. +There are two species (Chinook Salmon and Striped Bass) that appear to have sub-groups (i.e., "landlocked") but only that one specific sub-group appears in `WSlit`. The standard weight literature for these species did not identify the equation as only being for "landlocked" populations. However, these entries were added to facilitate use when calculating proportional size distribution (PSD) metrics,^[See [this vignette](https://fishr-core-team.github.io/FSA/articles/Computing_PSDs.html).] which were defined just for "landlocked" populations, and relative weight metrics with the same data.frame.^[As illustrated in [this companion vignette]().] The standard weight equations for these species can be accessed by either just the species name or the species name with the group in parentheses. However, note that they are the exact same information. ```{r} wsVal("Striped Bass") @@ -162,7 +162,7 @@ This calculation suggests that the standard weight for a 350 mm Largemouth Bass 100*650/ex1 ``` -This indicates that the individual is (slightly) heavier than a standard fish of the same length as this values is greater than 100. +This indicates that the individual is (slightly) heavier than a "standard fish" of the same length as this values is greater than 100. ## For Quadratic Equation A similar process can be followed for a species where the standard weight equation includes a quadratic term. The only "trick" here is to include the quadratic term multiplied by the **square** of the log10-transformed observed length when computing the standard weight. This calculation is illustrated below with a 500 mm and 1010 g Blue Sucker. @@ -184,15 +184,15 @@ A few things to consider when calculating relative weights for individuals. # Calculate Relative Weights for All of One Species It is not common to compute the standard and relative weights for a single individual as was done in the previous section. Rather, it is more useful to calculate these values for all individuals in a sample, and then summarize those values for an overall assessment of the condition of those individuals. -Consider the `CiscoTL` data.frame distributed with the `FSAdata` package that contains the lengths (mm) and weights (g) of Cisco (*Coregonus artedii*) sampled from Trout Lake, WI, USA over a 25 year period. Note that there are lots of missing weights in this data.frame. +Consider the `CiscoTL` data.frame distributed with the `FSAdata` package that contains the lengths (mm) and weights (g) of Cisco (*Coregonus artedii*) sampled from Trout Lake, WI, USA over a 25 year period. Note that there are many missing weights in this data.frame. ```{r} -data("CiscoTL",package="FSAdata") +data("CiscoTL",package="FSAdata") # retrieve the data.frame peek(CiscoTL,n=10) ``` ## "Manual" Calculations -The relative weight calculation begins by finding the specifics of the standard weight equation for Cisco. +The relative weight calculation begins by finding the specifics of the standard weight equation for Cisco and assigning them to an object (here, `wsC`). ```{r} ( wsC <- wsVal("Cisco") ) @@ -209,7 +209,7 @@ peek(CiscoTL,n=10) ``` ## Using the `WrAdd()` Convenience Function -`wrAdd()` can be used to add a relative weight variable to a data.frame for **all** species in the data.frame for which a standard weight equation exists.^[Though its use is illustrated here on a data.frame with only one species. See the next sections for an example with more species.] The main argument to `wrAdd()` is a formula of the form `weight~length+species` where `weight` is the observed weight variable, `length` is the observed length variable, and `species` is the name of the species variable. One constraint here is that the names in `species` must be spelled (and capitalized) exactly as in `WSlit`. In these data, the species name is in `spname` but is in all capital letters as "CISCO", rather than the required "Cisco". `capFirst()`^[From `FSA`.] may be used to convert a word to a form where just the first letter is capitalized, and is used below.^[Note that the `CiscoTL` data.frame was re-read so that the additions in the previous section were removed.] +`wrAdd()` can be used to add a relative weight variable to a data.frame for **all** species in the data.frame for which a standard weight equation exists.^[Though its use is illustrated here on a data.frame with only one species. See the next sections for an example with more species.] The main argument to `wrAdd()` is a formula of the form `weight~length+species` where `weight` is the name of the observed weight variable, `length` is the name of the observed length variable, and `species` is the name of the species variable. One constraint here is that the species names in the `species` variable must be spelled (and capitalized) exactly as in `WSlit`. In these data, the species name is in `spname` but is in all capital letters as "CISCO", rather than the required "Cisco". `capFirst()`^[From `FSA`.] may be used to convert a word to a form where just the first letter is capitalized, and is used below.^[Note that the `CiscoTL` data.frame was re-read so that the additions in the previous section were removed.] ```{r} data("CiscoTL",package="FSAdata") @@ -218,7 +218,7 @@ CiscoTL <- CiscoTL |> peek(CiscoTL,n=10) ``` -A more general approach to deal with species that are spelled differently than expected in `WSlit` is to provide a named list or vector that defines how the original species names (i.e., the values in the vector) relate to the species names required by `WSlit` (i.e., the names in the vector) to `thesaurus=`. `wrAdd()` will match the two names appropriately while creating the relative weight variable. +A more general approach to deal with species that are spelled differently than expected in `WSlit` is to provide a named list or vector that defines how the original species names (i.e., the items in the vector to the right of the `=`) relate to the species names required by `WSlit` (i.e., the names in the vector to the left of the `=`) to `thesaurus=`. `wrAdd()` will match the two names appropriately while creating the relative weight variable. ```{r} CiscoTL <- CiscoTL |> @@ -228,10 +228,10 @@ peek(CiscoTL,n=10) `thesaurus=` can be used even if only some of the species names are non-"standard." Additionally, the named list/vector in `thesaurus=` can contain names that don't exist in the original data.frame. Thus, a global thesaurus containing all species that *could* be encountered could be created, for example as an agency-wide definition, and used with a variety of specific data.frames. -`wrAdd()` handles species that have more than one standard weight equation^[As described previously.] with `WsOpts=`. For example, consider adding a relative weight variable to the `RuffeSLRH92` data.frame distributed with `FSAdata`. Note that there is no species variable, which is needed by `wrAdd()`.^[Note that `wrAdd()` is more convenient for data.frames with multiple species as will be illustrated in the next section.] Additionally, for simplicity of presentation, I removed several other variables that are not needed for this example. +`wrAdd()` handles species that have more than one standard weight equation^[As described previously.] with `WsOpts=`. For example, consider adding a relative weight variable to the `RuffeSLRH92` data.frame distributed with `FSAdata`. Note that there is no species variable, which is needed by `wrAdd()`, so one was added with `mutate()`.^[Note that `wrAdd()` is more convenient for data.frames with multiple species as will be illustrated in the next section.] Additionally, for simplicity of presentation, I removed several other variables (with `select()`) that are not needed for this example. ```{r} -data("RuffeSLRH92",package="FSAdata") +data("RuffeSLRH92",package="FSAdata") # retrieve the data.frame RuffeSLRH92 <- RuffeSLRH92 |> mutate(species="Ruffe") |> select(species,length,weight,sex) @@ -255,17 +255,17 @@ peek(RuffeSLRH92,n=10) ``` # Calculate Relative Weights for All of Multiple Species -The real value of `wrAdd()` is that it can be used to efficiently add a relative weight variable for multiple species in a single data.frame. This is illustrated below with examples for a variety of scenarios. +The real value of `wrAdd()` is that it can be used to efficiently add a relative weight variable for multiple species in a single data.frame. This is illustrated below for a variety of scenarios. ## "Good" Names and No Groups `InchLake2` distributed with `FSAdata` contains lengths and weights for several species captured from Inch Lake. These data provide a simple example for using `wrAdd()` because all species names are spelled as required and none of the species have sub-groups.^[See the next section for how to deal with these issues.] ```{r} -data("InchLake2",package="FSAdata") +data("InchLake2",package="FSAdata") # retrieve the data.frame peek(InchLake2,n=10) ``` -A complication here is that length and weight are in "mixed" units; i.e., inches for length and grams for weight. One or the other must be converted to the same unit type. Below length is converted to mm. +A complication here is that length and weight are in "mixed" units; i.e., inches for length and grams for weight. One or the other must be converted to the same unit type. Below length is converted to mm before `wrAdd()` is used to add a relative weight variable. ```{r} InchLake2 <- InchLake2 |> @@ -277,22 +277,20 @@ peek(InchLake2,n=10) Note that species without known standard weight equations in `WSlit` (e.g., Bluntnose Minnow) will have `NA` for the relative weight variable, as will individuals with lengths outside the range of lengths for which the standard weight equation should be applied. ## "Bad" Names and No Groups -Now consider the `BGHRfish` data.frame (distributed with the `FSAdata` package) that has the lengths (mm) and weights (g) of three species -- Smallmouth Bass, Largemouth Bass, and Bluegill -- from Big Hill Reservoir, KS. These four species do not have sub-groups defined in `WSlit`. However, observing the data below^[And [the documentation](https://fishr-core-team.github.io/FSAdata/reference/Herman.html).] shows that the species variable (`specCode`) contains codes for the species names rather than the names required by `PSDlit`. +Now consider the `BGHRfish` data.frame (distributed with the `FSAdata` package) that has the lengths (mm) and weights (g) of three species -- Smallmouth Bass, Largemouth Bass, and Bluegill -- from Big Hill Reservoir, KS. These three species do not have sub-groups defined in `WSlit`, but upon observing the data below^[And [the documentation](https://fishr-core-team.github.io/FSAdata/reference/Herman.html).] it is seen that the species variable (`specCode`) contains codes for the species names rather than the names required by `PSDlit`. ```{r} -data(BGHRfish,package="FSAdata") +data(BGHRfish,package="FSAdata") # retrieve the data.frame peek(BGHRfish,n=10) ``` -One complicating factor with these data is that `wrAdd()` expects a string in `species` rather than a numeric like `specCode`. Thus, below `specCode` will be converted to a character before using `wrAdd()`. - -One way to deal with the issue of "bad" species names is to use a named list or vector that defines how the names from `WSlit` should be matched to the names in the data.frame. For this purpose, the species names in `WSlit` are the names in the vector (i.e., before the `=`) and the species names in the data.frame are the values in the vector (i.e., after the `=`).^[The numeric species codes are in parentheses as `specCode` will be converted to a string before using `wrAdd()`.] +One way to deal with the issue of "bad" species names is to use a named list or vector that defines how the names from `WSlit` should be matched to the names in the data.frame. For this purpose, the species names in `WSlit` are the names in the vector (i.e., before the `=`) and the species names in the data.frame are the items in the vector (i.e., after the `=`).^[The numeric species codes are in parentheses as `specCode` will be converted to a string before using `wrAdd()`.] ```{r} thes <- c("Smallmouth Bass"="116","Largemouth Bass"="118","Bluegill"="122") ``` -This list/vector is then given to `thesaurus=` in `wrAdd()` which will perform the name matching while creating the GH length categories. +This list/vector is then given to `thesaurus=` in `wrAdd()` which will perform the name matching while creating the GH length categories. However, one complicating factor with these data is that `wrAdd()` expects a string in `species` (and, thus, `thesaurus=`) rather than a numeric like `specCode`. Thus, `specCode` is converted to a character below before using `wrAdd()`. ```{r} BGHRfish <- BGHRfish |> From 590008a53bb06db6016368787e09590fed69e8c7 Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Thu, 8 Jan 2026 08:47:54 -0600 Subject: [PATCH 15/16] More changes to PSD and Wr vignettes --- DESCRIPTION | 2 +- vignettes/articles/Computing_PSDs.qmd | 2 +- .../Computing_PSDs_and_RelativeWeights.qmd | 87 +++++++++++++++++++ .../articles/Computing_Relative_Weights.qmd | 2 +- 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 vignettes/articles/Computing_PSDs_and_RelativeWeights.qmd diff --git a/DESCRIPTION b/DESCRIPTION index 26d66cb6..f5c30e9b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FSA Version: 0.10.9000 -Date: 2025-12-21 +Date: 2026-1-7 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. Authors@R: c( diff --git a/vignettes/articles/Computing_PSDs.qmd b/vignettes/articles/Computing_PSDs.qmd index 9f243299..32474855 100644 --- a/vignettes/articles/Computing_PSDs.qmd +++ b/vignettes/articles/Computing_PSDs.qmd @@ -249,7 +249,7 @@ PSDWRtest$psd <- psdAdd(len~species2,data=PSDWRtest) peek(PSDWRtest,n=20) ``` -Handling these types of "issues" in conjunction with computing relative weights is illustrated in the companion [XXXX](). +Handling these types of "issues" in conjunction with computing relative weights is illustrated in [this companion vignette](https://fishr-core-team.github.io/FSA/articles/Computing_PSDs_and_RelativeWeights.html). diff --git a/vignettes/articles/Computing_PSDs_and_RelativeWeights.qmd b/vignettes/articles/Computing_PSDs_and_RelativeWeights.qmd new file mode 100644 index 00000000..cadf39be --- /dev/null +++ b/vignettes/articles/Computing_PSDs_and_RelativeWeights.qmd @@ -0,0 +1,87 @@ +--- +title: "Computing PSD and Relative Weight Metrics in FSA" +author: "Derek H. Ogle" +date: "`r Sys.Date()`" +format: + html: + toc: true + toc-depth: 2 + reference-location: margin + fig-cap-location: bottom + tbl-cap-location: top +knitr: + opts_chunk: + collapse: true + comment: '#>' +--- + +# Introduction +Other vignettes introduced using `FSA` to compute [proportional size distribution (PSD)](https://fishr-core-team.github.io/FSA/articles/Computing_PSDs.html) and [relative weight (i.e., condition)](https://fishr-core-team.github.io/FSA/articles/Computing_Relative_Weights.html) metrics. Both of those vignettes mentioned some peculiarities in their methodology related to when PSDs and relative weights were computed concurrently on the same data that contained some "issues." These peculiarities and issues are explained further and how to handle them are illustrated here. I urge you to explore those other vignettes before continuing here. + +The following packages are used herein. Note that the `FSA` functions described here were modified after version 0.9.6 and are thus **specific to FSA >v0.9.6**. + +```{r} +#| label: setup +#| results: hide +#| message: false +library(FSA) +library(dplyr) # mutate, select, filter, case_when +``` + +# Data +The hypothetical `PSDWRtest` data.frame distributed with `FSA` was created to purposely provide data for a variety of species that were realistic but created some issues for the `psdAdd()` and `wrAdd()` functions described in the other vignettes. + +```{r} +peek(PSDWRtest,n=20) +``` + +Ultimately it is best that you have a full understanding of the issues that may arise with your data by carefully examining your data and understanding the Gabelhouse (GH) length categories and relative weight equations for the species in your data. There are several "issues" that need to be addressed with the `PSDWRtest` data. + +First, Bluegill and Lake Trout exist in `PSDlit` and `WSlit` but appear as "Bluegill Sunfish" and "Lean Lake Trout" in `PSDWRtest`. + +Second, Brook Trout were sampled from a lotic ("Trout Lake") system and Brown Trout were sampled from a lotic ("Trout Lake") and a lentic ("Brush Creek") system. There are separate GH length categories and standard weight equations for these sub-groups for each species. + +Third, Muskellunge and Walleye provide a challenge because standard weight equations differ among sub-groups for each of these species, but the GH length categories do not differ among sub-groups. Walleye use separate standard weight equations depending on whether the individual's total length is less than 150 mm or not. Muskellunge have a sex-specific standard weight equation for when sex is known, but an overall equation for when sex is unknown. As will be seen, a new species variable will be created that incorporates the subgroup name into the "species name" for calculating standard weights (as was illustrated in [this vignette](https://fishr-core-team.github.io/FSA/articles/Computing_Relative_Weights.html)). Because the GH length categories don't differ by sub-group for either of these species, these new names are not needed when finding the GH length categories. However, for simplicity (as illustrated further below), these GH length categories have been duplicated for the sub-groups of each species and labelled with the combined species and sub-group name. This is illustrated below for muskellunge. + +```{r} +wsVal("Muskellunge (overall)") # different from next two +wsVal("Muskellunge (female)") +wsVal("Muskellunge (male)") +psdVal("Muskellunge (overall)") # exact same as next two +psdVal("Muskellunge (female)") +psdVal("Muskellunge (male)") +``` + +Fourth, Ruffe for which the reference quantile of the standard weight equation must be specified. + +# Adding GH Length Category and Wr Variables +The easiest way to deal with all of these "issues" except for the one related to Ruffe is to create a new "species" variable (i.e., `species2` below) that appends the specific sub-groups in parentheses to the species name. There are a variety of ways to do this and which way (is best or works) may depend on the specifics of the situation. Here, we use `case_when()` from `dplyr` with a series of statements that begin with a "condition" to the left of the `~` and new species "name" for that condition to the right of the `~`. The `.default=species` at the end puts the name from `species` into `species2` for all situations where none of the conditions above it are met (e.g., if `species` is "Yellow Perch" then `species2` will be "Yellow Perch"). + +```{r} +PSDWRtest <- PSDWRtest |> + mutate(species2=case_when( + species=="Bluegill Sunfish" ~ "Bluegill", + species=="Lean Lake Trout" ~ "Lake Trout", + species=="Brown Trout" & location=="Trout Lake" ~ "Brown Trout (lotic)", + species=="Brown Trout" & location=="Brushy Creek" ~ "Brown Trout (lentic)", + species=="Brook Trout" & location=="Trout Lake" ~ "Brook Trout (lotic)", + species=="Muskellunge" & sex=="M" ~ "Muskellunge (male)", + species=="Muskellunge" & sex=="F" ~ "Muskellunge (female)", + species=="Muskellunge" & sex=="U" ~ "Muskellunge (overall)", + species=="Muskellunge" & is.na(sex) ~ "Muskellunge (overall)", + species=="Walleye" & len>=150 ~ "Walleye (overall)", + species=="Walleye" & len<150 ~ "Walleye (30-149 mm)", + .default=species + )) +peek(PSDWRtest,n=20) +``` + +The GH length categories and relative weights for each fish (for species with standard weight equations) is added to this data.drame with `psdAdd()` and `wrAdd()` as described in the other vignettes, specifically noting the use of the "new" species variable `species2`. Further note the use of `wsOpts=` to define which reference quantile to use for the Ruffe standard weight equation. + +```{r} +PSDWRtest$psd <- psdAdd(len~species2,data=PSDWRtest) +PSDWRtest$wr <- wrAdd(wt~len+species2,data=PSDWRtest, + WsOpts=list(Ruffe=list(ref=75))) +peek(PSDWRtest,n=20) +``` + diff --git a/vignettes/articles/Computing_Relative_Weights.qmd b/vignettes/articles/Computing_Relative_Weights.qmd index a7fd3aec..d91f603a 100644 --- a/vignettes/articles/Computing_Relative_Weights.qmd +++ b/vignettes/articles/Computing_Relative_Weights.qmd @@ -117,7 +117,7 @@ wsVal("Ruffe") wsVal("Ruffe",ref=50) ``` -There are two species (Chinook Salmon and Striped Bass) that appear to have sub-groups (i.e., "landlocked") but only that one specific sub-group appears in `WSlit`. The standard weight literature for these species did not identify the equation as only being for "landlocked" populations. However, these entries were added to facilitate use when calculating proportional size distribution (PSD) metrics,^[See [this vignette](https://fishr-core-team.github.io/FSA/articles/Computing_PSDs.html).] which were defined just for "landlocked" populations, and relative weight metrics with the same data.frame.^[As illustrated in [this companion vignette]().] The standard weight equations for these species can be accessed by either just the species name or the species name with the group in parentheses. However, note that they are the exact same information. +There are two species (Chinook Salmon and Striped Bass) that appear to have sub-groups (i.e., "landlocked") but only that one specific sub-group appears in `WSlit`. The standard weight literature for these species did not identify the equation as only being for "landlocked" populations. However, these entries were added to facilitate use when calculating proportional size distribution (PSD) metrics,^[See [this vignette](https://fishr-core-team.github.io/FSA/articles/Computing_PSDs.html).] which were defined just for "landlocked" populations, and relative weight metrics with the same data.frame.^[As illustrated in [this companion vignette](https://fishr-core-team.github.io/FSA/articles/Computing_PSDs_and_RelativeWeights.html).] The standard weight equations for these species can be accessed by either just the species name or the species name with the group in parentheses. However, note that they are the exact same information. ```{r} wsVal("Striped Bass") From 236a55f858b22c83fa4e1ae088dd6e6afc541abc Mon Sep 17 00:00:00 2001 From: Derek Ogle Date: Fri, 9 Jan 2026 07:56:34 -0600 Subject: [PATCH 16/16] Prepping for v0.10.1 release --- DESCRIPTION | 4 +- NEWS.md | 6 +- _pkgdown.yml | 1 + cran-comments/cran-comments-v0_10_1.md | 10 + docs/LICENSE-text.html | 4 +- docs/authors.html | 12 +- docs/index.html | 4 +- docs/news/index.html | 48 +- docs/pkgdown.js | 192 +-- docs/pkgdown.yml | 7 +- docs/reference/BluegillJL.html | 4 +- docs/reference/BrookTroutTH-1.png | Bin 21141 -> 33269 bytes docs/reference/BrookTroutTH.html | 4 +- docs/reference/ChinookArg-1.png | Bin 42675 -> 68883 bytes docs/reference/ChinookArg.html | 4 +- docs/reference/CodNorwegian-1.png | Bin 46643 -> 63662 bytes docs/reference/CodNorwegian.html | 4 +- docs/reference/CutthroatAL.html | 4 +- docs/reference/Ecoli.html | 4 +- docs/reference/FSA-internals.html | 4 +- docs/reference/FSA.html | 4 +- docs/reference/Mirex.html | 6 +- docs/reference/PSDlit.html | 70 +- docs/reference/PikeNY.html | 4 +- docs/reference/PikeNYPartial1.html | 4 +- docs/reference/SMBassLS.html | 4 +- docs/reference/SMBassWB.html | 4 +- docs/reference/SpotVA1-1.png | Bin 39286 -> 66198 bytes docs/reference/SpotVA1.html | 4 +- docs/reference/Summarize.html | 78 +- docs/reference/WR79.html | 4 +- docs/reference/WSlit.html | 71 +- docs/reference/WhitefishLC.html | 4 +- docs/reference/addZeroCatch.html | 4 +- docs/reference/ageBias-1.png | Bin 35754 -> 43693 bytes docs/reference/ageBias-10.png | Bin 32624 -> 41254 bytes docs/reference/ageBias-11.png | Bin 34819 -> 42556 bytes docs/reference/ageBias-12.png | Bin 76267 -> 67948 bytes docs/reference/ageBias-13.png | Bin 67004 -> 62619 bytes docs/reference/ageBias-14.png | Bin 69658 -> 63535 bytes docs/reference/ageBias-15.png | Bin 77413 -> 69947 bytes docs/reference/ageBias-16.png | Bin 61350 -> 53927 bytes docs/reference/ageBias-17.png | Bin 67965 -> 63693 bytes docs/reference/ageBias-18.png | Bin 62698 -> 54907 bytes docs/reference/ageBias-19.png | Bin 85264 -> 84067 bytes docs/reference/ageBias-2.png | Bin 38136 -> 46342 bytes docs/reference/ageBias-20.png | Bin 78774 -> 74764 bytes docs/reference/ageBias-21.png | Bin 78675 -> 76518 bytes docs/reference/ageBias-22.png | Bin 81585 -> 78126 bytes docs/reference/ageBias-3.png | Bin 36669 -> 45376 bytes docs/reference/ageBias-4.png | Bin 51274 -> 66254 bytes docs/reference/ageBias-5.png | Bin 49940 -> 57091 bytes docs/reference/ageBias-6.png | Bin 34456 -> 42445 bytes docs/reference/ageBias-7.png | Bin 35627 -> 44323 bytes docs/reference/ageBias-8.png | Bin 36199 -> 44939 bytes docs/reference/ageBias-9.png | Bin 37383 -> 47080 bytes docs/reference/ageBias.html | 10 +- docs/reference/agePrecision-1.png | Bin 23261 -> 34389 bytes docs/reference/agePrecision-10.png | Bin 41607 -> 64350 bytes docs/reference/agePrecision-2.png | Bin 42024 -> 63840 bytes docs/reference/agePrecision-3.png | Bin 41383 -> 63006 bytes docs/reference/agePrecision-4.png | Bin 25213 -> 38961 bytes docs/reference/agePrecision-5.png | Bin 38612 -> 60568 bytes docs/reference/agePrecision-6.png | Bin 49927 -> 75463 bytes docs/reference/agePrecision-7.png | Bin 51154 -> 77232 bytes docs/reference/agePrecision-8.png | Bin 30282 -> 47046 bytes docs/reference/agePrecision-9.png | Bin 46072 -> 71372 bytes docs/reference/agePrecision.html | 1872 +++++++++++++++--------- docs/reference/alkAgeDist.html | 4 +- docs/reference/alkIndivAge.html | 32 +- docs/reference/alkMeanVar.html | 4 +- docs/reference/alkPlot-1.png | Bin 50149 -> 57887 bytes docs/reference/alkPlot-10.png | Bin 104525 -> 110419 bytes docs/reference/alkPlot-2.png | Bin 50579 -> 58269 bytes docs/reference/alkPlot-3.png | Bin 45684 -> 53732 bytes docs/reference/alkPlot-4.png | Bin 23893 -> 32403 bytes docs/reference/alkPlot-5.png | Bin 63384 -> 70048 bytes docs/reference/alkPlot-6.png | Bin 102644 -> 113642 bytes docs/reference/alkPlot-7.png | Bin 114789 -> 128847 bytes docs/reference/alkPlot-8.png | Bin 102949 -> 113752 bytes docs/reference/alkPlot-9.png | Bin 120281 -> 107633 bytes docs/reference/alkPlot.html | 4 +- docs/reference/binCI.html | 4 +- docs/reference/capHistConvert.html | 4 +- docs/reference/capHistSum-1.png | Bin 39822 -> 62101 bytes docs/reference/capHistSum-2.png | Bin 29776 -> 50291 bytes docs/reference/capHistSum-3.png | Bin 27631 -> 46083 bytes docs/reference/capHistSum.html | 4 +- docs/reference/catchCurve-1.png | Bin 18145 -> 27878 bytes docs/reference/catchCurve-2.png | Bin 29218 -> 46061 bytes docs/reference/catchCurve-3.png | Bin 29108 -> 45982 bytes docs/reference/catchCurve-4.png | Bin 31225 -> 48936 bytes docs/reference/catchCurve-5.png | Bin 31234 -> 48992 bytes docs/reference/catchCurve.html | 14 +- docs/reference/chapmanRobson-1.png | Bin 18145 -> 27878 bytes docs/reference/chapmanRobson-2.png | Bin 24340 -> 37531 bytes docs/reference/chapmanRobson-3.png | Bin 24188 -> 35797 bytes docs/reference/chapmanRobson-4.png | Bin 24683 -> 36124 bytes docs/reference/chapmanRobson-5.png | Bin 24340 -> 37531 bytes docs/reference/chapmanRobson-6.png | Bin 24630 -> 38007 bytes docs/reference/chapmanRobson.html | 4 +- docs/reference/col2rgbt.html | 4 +- docs/reference/depletion-1.png | Bin 40183 -> 53409 bytes docs/reference/depletion-2.png | Bin 39907 -> 52394 bytes docs/reference/depletion-3.png | Bin 42487 -> 57775 bytes docs/reference/depletion.html | 4 +- docs/reference/dunnTest.html | 4 +- docs/reference/expandCounts.html | 118 +- docs/reference/expandLenFreq.html | 4 +- docs/reference/extraTests.html | 22 +- docs/reference/fact2num.html | 5 +- docs/reference/fishR.html | 4 +- docs/reference/geomean.html | 8 +- docs/reference/growthModels-1.png | Bin 28849 -> 45785 bytes docs/reference/growthModels-10.png | Bin 31841 -> 51386 bytes docs/reference/growthModels-11.png | Bin 31806 -> 51121 bytes docs/reference/growthModels-12.png | Bin 32436 -> 52155 bytes docs/reference/growthModels-13.png | Bin 53520 -> 70850 bytes docs/reference/growthModels-2.png | Bin 30198 -> 48125 bytes docs/reference/growthModels-3.png | Bin 32479 -> 52517 bytes docs/reference/growthModels-4.png | Bin 31587 -> 51600 bytes docs/reference/growthModels-5.png | Bin 32845 -> 52823 bytes docs/reference/growthModels-6.png | Bin 33189 -> 53063 bytes docs/reference/growthModels-7.png | Bin 33312 -> 53526 bytes docs/reference/growthModels-8.png | Bin 32595 -> 52690 bytes docs/reference/growthModels-9.png | Bin 39624 -> 61040 bytes docs/reference/growthModels.html | 338 +++-- docs/reference/headtail.html | 4 +- docs/reference/hist.formula-1.png | Bin 26980 -> 41830 bytes docs/reference/hist.formula-2.png | Bin 30906 -> 47437 bytes docs/reference/hist.formula-3.png | Bin 31008 -> 46389 bytes docs/reference/hist.formula-4.png | Bin 19920 -> 29795 bytes docs/reference/hist.formula-5.png | Bin 20141 -> 30436 bytes docs/reference/hist.formula-6.png | Bin 29981 -> 44914 bytes docs/reference/hist.formula.html | 6 +- docs/reference/histFromSum-1.png | Bin 19106 -> 27080 bytes docs/reference/histFromSum-2.png | Bin 19114 -> 27072 bytes docs/reference/histFromSum-3.png | Bin 19109 -> 27090 bytes docs/reference/histFromSum-4.png | Bin 19113 -> 27087 bytes docs/reference/histFromSum-5.png | Bin 19101 -> 27069 bytes docs/reference/histFromSum-6.png | Bin 19088 -> 27049 bytes docs/reference/histFromSum.html | 4 +- docs/reference/hyperCI.html | 4 +- docs/reference/index.html | 278 ++-- docs/reference/knitUtil.html | 4 +- docs/reference/ksTest.html | 14 +- docs/reference/lagratio.html | 4 +- docs/reference/lencat.html | 72 +- docs/reference/logbtcf.html | 18 +- docs/reference/lwCompPreds-1.png | Bin 64292 -> 80541 bytes docs/reference/lwCompPreds-2.png | Bin 53613 -> 69644 bytes docs/reference/lwCompPreds-3.png | Bin 58928 -> 73452 bytes docs/reference/lwCompPreds-4.png | Bin 53784 -> 67410 bytes docs/reference/lwCompPreds-5.png | Bin 41619 -> 60504 bytes docs/reference/lwCompPreds-6.png | Bin 64292 -> 80541 bytes docs/reference/lwCompPreds.html | 6 +- docs/reference/metaM.html | 72 +- docs/reference/mrClosed-1.png | Bin 56294 -> 65786 bytes docs/reference/mrClosed-2.png | Bin 24020 -> 36433 bytes docs/reference/mrClosed.html | 4 +- docs/reference/mrOpen.html | 4 +- docs/reference/nlsBoot.html | 4 +- docs/reference/nlsTracePlot-1.png | Bin 97998 -> 110399 bytes docs/reference/nlsTracePlot-2.png | Bin 72934 -> 90969 bytes docs/reference/nlsTracePlot.html | 4 +- docs/reference/perc.html | 4 +- docs/reference/plotAB-1.png | Bin 44553 -> 51664 bytes docs/reference/plotAB-2.png | Bin 47725 -> 56486 bytes docs/reference/plotAB-3.png | Bin 46308 -> 54280 bytes docs/reference/plotAB-4.png | Bin 40187 -> 53300 bytes docs/reference/plotAB.html | 8 +- docs/reference/poiCI.html | 4 +- docs/reference/psdAdd.html | 384 +++-- docs/reference/psdCI.html | 4 +- docs/reference/psdCalc.html | 198 +-- docs/reference/psdPlot-1.png | Bin 38192 -> 48319 bytes docs/reference/psdPlot-2.png | Bin 37813 -> 47825 bytes docs/reference/psdPlot-3.png | Bin 27097 -> 37326 bytes docs/reference/psdPlot.html | 4 +- docs/reference/psdVal.html | 106 +- docs/reference/rSquared.html | 4 +- docs/reference/rcumsum.html | 16 +- docs/reference/removal.html | 4 +- docs/reference/se.html | 4 +- docs/reference/srStarts-1.png | Bin 45944 -> 60213 bytes docs/reference/srStarts-2.png | Bin 38590 -> 51280 bytes docs/reference/srStarts-3.png | Bin 38519 -> 51698 bytes docs/reference/srStarts-4.png | Bin 46552 -> 61437 bytes docs/reference/srStarts-5.png | Bin 41059 -> 52765 bytes docs/reference/srStarts.html | 4 +- docs/reference/sumTable.html | 66 +- docs/reference/tictactoe-1.png | Bin 26088 -> 38509 bytes docs/reference/tictactoe-2.png | Bin 32065 -> 47607 bytes docs/reference/tictactoe.html | 20 +- docs/reference/validn.html | 6 +- docs/reference/vbStarts-1.png | Bin 66050 -> 86815 bytes docs/reference/vbStarts-2.png | Bin 65212 -> 86078 bytes docs/reference/vbStarts-3.png | Bin 69016 -> 91807 bytes docs/reference/vbStarts-4.png | Bin 67778 -> 89480 bytes docs/reference/vbStarts-5.png | Bin 68302 -> 93241 bytes docs/reference/vbStarts.html | 4 +- docs/reference/wrAdd.html | 254 ++-- docs/reference/wsVal.html | 275 ++-- docs/sitemap.xml | 2 + 204 files changed, 2944 insertions(+), 1973 deletions(-) create mode 100644 cran-comments/cran-comments-v0_10_1.md diff --git a/DESCRIPTION b/DESCRIPTION index f5c30e9b..cbac8c74 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: FSA -Version: 0.10.9000 +Version: 0.10.1 Date: 2026-1-7 Title: Simple Fisheries Stock Assessment Methods Description: A variety of simple fish stock assessment methods. @@ -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 debb9252..a4187fb6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# FSA 0.10.9000 +# 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. @@ -134,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/_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/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