Skip to content

Commit f5e8de1

Browse files
Merge pull request #29 from alaska-groundfish-efh/dev
Merge in dev changes
2 parents 2dce1c8 + 733415a commit f5e8de1

File tree

93 files changed

+4754
-4356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+4754
-4356
lines changed

.Rbuildignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
^EFHSDM\.Rproj$
22
^\.Rproj\.user$
33
^dev$
4-
^R/Meatgrinder5\.R$
54
^LICENSE\.md$
65
^doc$
76
^Meta$
7+
^CONTRIBUTING\.md$
8+
^\.github$
9+
^Meatgrinder6_mcs.R

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ vignettes/*.pdf
4444
inst/doc
4545
/doc/
4646
/Meta/
47+
48+
Meatgrinder6_mcs.R

DESCRIPTION

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,25 @@ Authors@R:
88
comment = c(ORCID = "0000-0003-2663-9243")),
99
person(c("James", "T."), "Thorson", email = "james.thorson@noaa.gov", role = c("aut"),
1010
comment = c(ORCID = "0000-0001-7415-1010")),
11-
person("Jodi", "Pirtle", ,email = "jodi.pirtle@noaa.gov", role = c("aut"),
11+
person(c("Jodi", "L."), "Pirtle", email = "jodi.pirtle@noaa.gov", role = c("aut"),
1212
comment = c(ORCID = "0000-0002-4421-8234")),
1313
person(c("Margaret","C."), "Siple", email = "margaret.siple@noaa.gov", role = c("aut", "com"),
14-
comment = c(ORCID = "0000-0002-4260-9856"))
14+
comment = c(ORCID = "0000-0002-4260-9856")),
15+
person(c("Mason","J."), "Smith", email = "mason.smith@noaa.gov", role = c("aut", "com"),
16+
comment = c(ORCID = "0000-0002-3132-6869")),
17+
person(c("Mallarie", "E."), "Yeager", email = "mallarie.yeager@noaa.gov", role = c("aut", "com"),
18+
comment = c(ORCID = " 0000-0002-5513-2583"))
1519
)
16-
Description: This package fits species distribution models (SDMs) to groundfish and crab data from the Eastern Bering Sea, Aleutian Islands, and Gulf of Alaska. These SDMs were used in the 2022 EFH 5-Year Review.
20+
Description: This package fits species distribution models (SDMs) to groundfish and crab data from the Eastern Bering Sea, Aleutian Islands, and Gulf of Alaska. These SDMs were used in the 2023 EFH 5-Year Review.
1721
License: MIT + file LICENSE
1822
Encoding: UTF-8
1923
Roxygen: list(markdown = TRUE)
2024
RoxygenNote: 7.3.2
2125
Suggests:
2226
knitr,
2327
rmarkdown,
24-
gridExtra
28+
gridExtra,
29+
testthat (>= 3.0.0)
2530
VignetteBuilder: knitr
2631
Imports:
2732
ggplot2,
@@ -43,3 +48,4 @@ Depends:
4348
R (>= 3.5.0)
4449
LazyData:
4550
false
51+
Config/testthat/edition: 3

R/AssembleGAMFormula.R

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#' Make a GAM formula
2+
#'
3+
#' @description Improved version designed to use the tables produced by the Autodetect functions
4+
# allows for easily dropping terms for things like term selections and deviance explained.
5+
#' @param yvar Name of dependent variable for gam models
6+
#' @param gam.table Data frame of parameters for GAM formula
7+
#' @param hgam Logical; do you want an hgam formula
8+
#'
9+
#' @return Returns a formula object, or list of formulas for hgam
10+
#' @export
11+
#'
12+
#' @examples
13+
AssembleGAMFormula <- function(yvar, gam.table, hgam = F) {
14+
15+
# logic to handle different possibilities to supply for hgam
16+
if (hgam) {
17+
if (is.data.frame(gam.table[[1]])) {
18+
gam.table1 <- gam.table[[1]]
19+
} else {
20+
gam.table1 <- gam.table
21+
}
22+
if (is.data.frame(gam.table[[2]])) {
23+
gam.table2 <- gam.table[[2]]
24+
} else {
25+
gam.table2 <- gam.table1
26+
}
27+
form.list <- list(gam.table1, gam.table2)
28+
} else {
29+
gam.table1 <- gam.table
30+
form.list <- list(gam.table1)
31+
}
32+
33+
for (f in 1:length(form.list)) {
34+
g.table <- form.list[[f]]
35+
out.terms <- rep(NA, nrow(g.table))
36+
37+
for (t in 1:nrow(g.table)) {
38+
if (g.table$type[t] == "smooth") {
39+
out.term0 <- paste0("s(", g.table$term[t])
40+
}
41+
if (g.table$type[t] == "factor") {
42+
out.term0 <- paste0("as.factor(", g.table$term[t])
43+
}
44+
if (g.table$type[t] == "offset") {
45+
out.term0 <- paste0("offset(", g.table$term[t])
46+
}
47+
48+
if (is.na(g.table$term2[t]) == F) {
49+
out.term0 <- paste0(out.term0, ",", g.table$term2[t])
50+
}
51+
if (is.na(g.table$bs[t]) == F) {
52+
out.term0 <- paste0(out.term0, ",bs='", g.table$bs[t], "'")
53+
}
54+
if (is.na(g.table$k[t]) == F) {
55+
out.term0 <- paste0(out.term0, ",k=", g.table$k[t])
56+
}
57+
if (is.na(g.table$m[t]) == F & is.na(g.table$m2[t])) {
58+
out.term0 <- paste0(out.term0, ",m=", g.table$m[t])
59+
}
60+
if (is.na(g.table$m[t]) == F & is.na(g.table$m2[t]) == F) {
61+
out.term0 <- paste0(out.term0, ",m=c(", g.table$m[t], ",", g.table$m2[t], ")")
62+
}
63+
out.terms[t] <- paste0(out.term0, ")")
64+
if (g.table$type[t] == "linear") {
65+
out.terms[t] <- g.table$term[t]
66+
}
67+
}
68+
69+
if (f == 1) {
70+
out.form <- list(stats::as.formula(paste0(yvar, " ~ ", paste(out.terms, collapse = " + "))))
71+
}
72+
if (f > 1) {
73+
out.form[[f]] <- stats::as.formula(paste0(" ~ ", paste(out.terms, collapse = " + ")))
74+
}
75+
}
76+
if (
77+
length(form.list) == 1) {
78+
return(out.form[[1]])
79+
} else {
80+
return(out.form)
81+
}
82+
}

R/AutodetectGAMTerms.R

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#' Auto-detect GAM terms
2+
#'
3+
#' @description This is a useful function that returns a table of the terms in a GAM, whether they are a one dimensional (linear) term, a two dimensional smooth, or a factor. Also detects the offset.
4+
#' @param model A fitted GAM model object
5+
#' @param hgam character describing how to handle hgams; use "d" for the density model, "p" for the prob model, or "b" or "all" for both
6+
#'
7+
#' @return returns a data frame with columns describing the name and type of all model components and relevant smoother parameters
8+
#' @export
9+
#'
10+
#' @examples
11+
AutodetectGAMTerms <- function(model, hgam = "all") {
12+
n.formulas <- 1
13+
if (model$family$family == "ziplss" & hgam %in% c("b", "both", "all")) {
14+
n.formulas <- 2
15+
}
16+
17+
for (f in 1:n.formulas) {
18+
form.index <- 3
19+
20+
# a lot of special handling for ziplss models
21+
if (model$family$family == "ziplss") {
22+
if (hgam %in% c("b", "both", "all")) {
23+
form1 <- stats::formula(model)[[f]]
24+
}
25+
if (hgam %in% c("d", "dens", "density")) {
26+
form1 <- stats::formula(model)[[1]]
27+
}
28+
if (hgam %in% c("p", "prob", "probability")) {
29+
form1 <- stats::formula(model)[[2]]
30+
}
31+
} else {
32+
form1 <- stats::formula(model)
33+
}
34+
35+
terms <- trimws(strsplit(as.character(form1[[length(form1)]]), split = "[+]")[[2]])
36+
37+
# loop through and figure out the information for the table
38+
type.dat <- data.frame(type = rep(NA, length(terms)), dims = 1, term = NA, term2 = NA, bs = NA, k = NA, m = NA, m2 = NA)
39+
for (t in 1:length(terms)) {
40+
x <- terms[t]
41+
x2 <- strsplit(x, split = "[(=)]")[[1]]
42+
# linear terms
43+
if (length(x2) == 1) {
44+
type.dat$type[t] <- "linear"
45+
type.dat$term[t] <- x2
46+
} else {
47+
# smoothed terms
48+
if (x2[1] %in% c("s", "te")) {
49+
dims <- length(strsplit(x2[2], split = ", ")[[1]]) - 1
50+
for (n in 1:dims) {
51+
type.dat[t, 2 + n] <- strsplit(x2[2], split = ", ")[[1]][n]
52+
}
53+
type.dat$type[t] <- "smooth"
54+
type.dat$dims[t] <- dims
55+
56+
# find smoother basis
57+
formula.options <- strsplit(x, split = ",")[[1]]
58+
bs.spot <- which(unlist(lapply(strsplit(formula.options, "="), FUN = function(x) {
59+
return(trimws(x[1]))
60+
})) == "bs")
61+
if (length(bs.spot) > 0) {
62+
type.dat$bs[t] <- strsplit(formula.options[bs.spot], split = "\"")[[1]][2]
63+
}
64+
65+
# find smoother k
66+
k.spot <- which(unlist(lapply(strsplit(formula.options, "="), FUN = function(x) {
67+
return(trimws(x[1]))
68+
})) == "k")
69+
if (length(k.spot) > 0) {
70+
type.dat$k[t] <- trimws(strsplit(strsplit(formula.options[k.spot], split = "=")[[1]][2], split = "[)]")[[1]])
71+
}
72+
73+
# find penalty m, which can be complicated
74+
m.spot <- which(unlist(lapply(strsplit(formula.options, "="), FUN = function(x) {
75+
return(trimws(x[1]))
76+
})) == "m")
77+
if (length(m.spot) > 0) {
78+
if ("c" %in% strsplit(formula.options[m.spot], split = "")[[1]]) {
79+
m.spot <- c(m.spot, m.spot + 1)
80+
}
81+
for (n in 1:length(m.spot)) {
82+
m1 <- trimws(formula.options[m.spot][n])
83+
if (n == 1) {
84+
m2 <- trimws(strsplit(m1, split = "=")[[1]][2])
85+
} else {
86+
m2 <- m1
87+
}
88+
m3 <- trimws(strsplit(m2, split = "[()]")[[1]])
89+
type.dat[t, 6 + n] <- suppressWarnings(stats::na.omit(as.numeric(m3))[1])
90+
}
91+
}
92+
}
93+
# factor terms
94+
if (x2[1] == "as.factor") {
95+
type.dat$type[t] <- "factor"
96+
type.dat$term[t] <- x2[2]
97+
}
98+
}
99+
}
100+
# Make the table
101+
terms2 <- unlist(strsplit(x = names(model$model), split = "[()]"))
102+
off.term <- which(terms2 == "offset") + 1
103+
if (length(off.term) > 0) {
104+
type.dat <- rbind(type.dat, data.frame(type = "offset", dims = 1, term = terms2[off.term], term2 = NA, bs = NA, k = NA, m = NA, m2 = NA))
105+
}
106+
# if multiple formulas, need to make a list
107+
if (n.formulas > 1) {
108+
if (f == 1) {
109+
out.dat <- list(type.dat)
110+
} else {
111+
out.dat[[f]] <- type.dat
112+
}
113+
} else {
114+
out.dat <- type.dat
115+
}
116+
}
117+
return(out.dat)
118+
}

0 commit comments

Comments
 (0)