-
Notifications
You must be signed in to change notification settings - Fork 0
Monitor population parameters #141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1194641
216de96
3b44be0
d167acf
806389c
12fd909
9e5b61f
c1956ce
c1ccc63
23cb959
ab0876b
9c6255d
e819741
808eb60
6f7b224
1ea38a0
920ae66
b78a454
2d5a841
6b63587
2edf8ef
a9fea4c
4691b50
80072bc
29f2431
b79ed5f
b510d60
25eb682
0b1d83a
f3f19ec
d6186c8
7978f45
d63030c
af36115
554866f
7a7b66b
0652a2c
be6eb67
167e335
5dc667c
492e274
1b4214c
047e8bc
a19acf9
f318682
aba2dd4
9ce51ac
4476ace
9fd81e8
02ce138
256e8fa
9ba9c86
cf8e861
5322f08
4aafc38
40a2e53
41d541d
d37106f
ebf52f2
ad73d41
750c490
4b0a542
63a89e5
a5b3aac
e18802b
26d3f67
f2a6b12
8093b58
c343ab5
84efc38
bf3e7f4
35503de
9986651
080f384
ccb8b37
7102fda
98a0aeb
20d31c6
a845269
0ec3ca6
12158b6
4f55f09
82a397f
08aa4ec
3f1cf90
5568f37
5f62438
92e54f0
3ea9aca
516c3e7
05bf272
04ed39d
d8fa544
5974909
c3ea272
132c8d9
42cf453
bd6981a
55228c8
6c9ea64
bb19344
834602b
f195188
b119c6a
59c08b9
d0b42fb
8fece48
d1ed607
f9bea33
cb57cc9
aff25bc
49e42c5
0248a4e
9d3efc6
361e681
f27abb7
e906a8d
560da05
72082ff
431975c
46b991d
79956b9
5048e36
860a894
640c5c2
9b67516
c6268c7
1179b9d
548483c
3dadddc
d761107
858b47c
5e25983
4163a8c
64e068e
6038fb7
2b03cbe
14d9eac
232855d
c14bba8
9c611b9
c7f6779
3be11bd
936ff74
d282ba5
34ebde3
9b93578
36891b9
43129e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,11 @@ | |
| #' should be included as an element of the [list] object returned by `run_mod()` | ||
| #' (see `Value` section below for details). | ||
| #' Note: These objects can be large. | ||
| #' @returns An `sr_model` class object: a subclass of [dplyr::tbl_df] that | ||
| #' @param with_pop_params A [logical] value specifying whether population | ||
| #' level parameters should be included as an attribute entitled | ||
| #' `population_params`. Excluded as default. | ||
| #' Note: These objects can be large. | ||
| #' @returns An `sr_model` class object: a subclass of [tibble::tbl_df] that | ||
| #' contains MCMC samples from the joint posterior distribution of the model | ||
| #' parameters, conditional on the provided input `data`, | ||
| #' including the following: | ||
|
|
@@ -49,6 +53,17 @@ | |
| #' - `nIterations`: Number of iteration specified. | ||
| #' - `nBurnin`: Number of burn ins. | ||
| #' - `nThin`: Thinning number (niter/nmc). | ||
| #' - `population_params`: Optionally included modeled population parameters | ||
| #' indexed by | ||
| #' `Iteration`, | ||
| #' `Chain`, `Parameter`, `Iso_type`, and `Stratification`. Excluded as | ||
| #' default. Includes the following modeled population parameters: | ||
| #' - `mu.par` = The population means of the host-specific model parameters | ||
| #' (on logarithmic scales). | ||
| #' - `prec.par` = The population precision matrix of the hyperparameters | ||
| #' (with diagonal elements equal to inverse variances). | ||
| #' - `prec.logy` = A vector of population precisions (inverse variances), | ||
| #' one per antigen/isotype combination. | ||
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #' - `priors`: A [list] that summarizes the input priors, including: | ||
| #' - `mu_hyp_param` | ||
| #' - `prec_hyp_param` | ||
|
|
@@ -71,6 +86,7 @@ run_mod <- function(data, | |
| niter = 100, | ||
| strat = NA, | ||
| with_post = FALSE, | ||
| with_pop_params = FALSE, | ||
| ...) { | ||
| ## Conditionally creating a stratification list to loop through | ||
| if (is.na(strat)) { | ||
|
|
@@ -80,15 +96,14 @@ run_mod <- function(data, | |
| } | ||
|
|
||
| ## Creating a shell to output results | ||
| jags_out <- data.frame( | ||
| "Iteration" = NA, | ||
| "Chain" = NA, | ||
| "Parameter" = NA, | ||
| "value" = NA, | ||
| "Parameter_sub" = NA, | ||
| "Subject" = NA, | ||
| "Iso_type" = NA, | ||
| "Stratification" = NA | ||
| jags_out <- tibble::tibble( | ||
| "Iteration" = integer(), | ||
| "Chain" = integer(), | ||
| "value" = numeric(), | ||
| "Subject" = character(), | ||
| "Parameter" = character(), | ||
| "Iso_type" = character(), | ||
| "Stratification" = character() | ||
| ) | ||
|
|
||
| ## Creating output list for jags.post | ||
|
|
@@ -118,6 +133,11 @@ run_mod <- function(data, | |
| nthin <- round(niter / nmc) # thinning needed to produce nmc from niter | ||
|
|
||
| tomonitor <- c("y0", "y1", "t1", "alpha", "shape") | ||
| # Conditional statement for including population parameters | ||
| if (with_pop_params) { | ||
| tomonitor <- c(tomonitor, "mu.par", "prec.par", | ||
| "prec.logy") | ||
| } | ||
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| jags_post <- runjags::run.jags( | ||
| model = file_mod, | ||
|
|
@@ -138,61 +158,106 @@ run_mod <- function(data, | |
| jags_post_final[[i]] <- jags_post | ||
|
|
||
| # Unpacking and cleaning MCMC output. | ||
| jags_unpack <- ggmcmc::ggs(jags_post[["mcmc"]]) | ||
| jags_packed <- ggmcmc::ggs(jags_post[["mcmc"]]) | ||
|
|
||
| # Adding attributes | ||
| mod_atts <- attributes(jags_unpack) | ||
| # Only keeping necessary attributes | ||
| mod_atts <- mod_atts[4:8] | ||
|
|
||
| mod_atts <- attributes(jags_packed) | ||
| # Select necessary attributes by name for robustness across platforms | ||
| mod_atts <- mod_atts[c("nChains", "nParameters", "nIterations", | ||
| "nBurnin", "nThin", "description")] | ||
|
|
||
| # extracting antigen-iso combinations to correctly number | ||
| # then by the order they are estimated by the program. | ||
| # them by the order they are estimated by the program. | ||
| iso_dat <- data.frame(attributes(longdata)$antigens) | ||
| iso_dat <- iso_dat |> dplyr::mutate(Subnum = as.numeric(row.names(iso_dat))) | ||
| # Working with jags unpacked ggs outputs to clarify parameter and subject | ||
| jags_unpack <- jags_unpack |> | ||
| dplyr::mutate( | ||
| Subnum = sub(".*,", "", .data$Parameter), | ||
| Parameter_sub = sub("\\[.*", "", .data$Parameter), | ||
| Subject = sub("\\,.*", "", .data$Parameter) | ||
| ) |> | ||
| dplyr::mutate( | ||
| Subnum = as.numeric(sub("\\].*", "", .data$Subnum)), | ||
| Subject = sub(".*\\[", "", .data$Subject) | ||
| ) | ||
| # Merging isodat in to ensure we are classifying antigen_iso | ||
| jags_unpack <- dplyr::left_join(jags_unpack, iso_dat, by = "Subnum") | ||
| iso_dat <- iso_dat |> dplyr::mutate(Subnum = row.names(iso_dat)) | ||
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Unpacking the mcmc object | ||
| jags_unpacked <- unpack_jags(jags_packed) | ||
|
|
||
| # Merging isodat in to ensure we are classifying antigen_iso. | ||
| jags_unpacked <- dplyr::left_join(jags_unpacked, iso_dat, | ||
| by = "Subnum") | ||
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Adding in ID name | ||
| ids <- data.frame(attr(longdata, "ids")) |> | ||
| mutate(Subject = as.character(dplyr::row_number())) | ||
| jags_unpack <- dplyr::left_join(jags_unpack, ids, by = "Subject") | ||
| jags_final <- jags_unpack |> | ||
| dplyr::select(!c("Subnum", "Subject")) |> | ||
| dplyr::mutate(Subject = as.character(dplyr::row_number())) | ||
| jags_final <- dplyr::left_join(jags_unpacked, ids, | ||
| by = "Subject") |> | ||
| dplyr::rename(c("Iso_type" = "attributes.longdata..antigens", | ||
| "Subject" = "attr.longdata...ids..")) | ||
| "Subject_mcmc" = "attr.longdata...ids..")) |> | ||
| # Subject handling: | ||
| # * For individual-level parameters, the left join above finds a row in | ||
| # attr(longdata, "ids"), so Subject_mcmc contains the subject ID. | ||
| # * For population-level parameters (e.g., mu.par, prec.par, prec.logy), | ||
| # there is no matching ID, so Subject_mcmc is NA. In that case we | ||
| # intentionally keep the original Subject value from unpack_jags, | ||
| # which holds the parameter name and serves as the identifier. | ||
| dplyr::mutate(Subject_mcmc = ifelse(is.na(.data$Subject_mcmc), | ||
| .data$Subject, | ||
| .data$Subject_mcmc)) |> | ||
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| # At this point, jags_unpacked contains: | ||
| # * Parameter: original JAGS parameter names (e.g., "y0[1,2]") | ||
| # * Param: cleaned parameter names used elsewhere in the package. | ||
| # We drop the original JAGS-style Parameter column and keep the | ||
| # cleaned names, then rename Param back to Parameter so that all | ||
| # downstream code consistently uses a single "Parameter" column | ||
| # containing cleaned parameter names. | ||
| # Drop the temporary Subject (now only used as a fallback for population | ||
| # parameters) and rename Subject_mcmc back to Subject for downstream use. | ||
| dplyr::select(!c("Subnum", "Subject", "Parameter")) |> | ||
| dplyr::rename(c("Subject" = "Subject_mcmc", | ||
| "Parameter" = "Param")) | ||
sschildhauer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Creating a label for the stratification, if there is one. | ||
| # If not, will add in "None". | ||
| jags_final$Stratification <- i | ||
| ## Creating output | ||
| jags_out <- data.frame(rbind(jags_out, jags_final)) | ||
| # Creating output as a data frame with the | ||
| # jags output results for each stratification rbinded. | ||
| jags_out <- dplyr::bind_rows(jags_out, jags_final) | ||
| } | ||
| # Ensuring output does not have any NAs | ||
| jags_out <- jags_out[complete.cases(jags_out), ] | ||
| # Outputting the finalized jags output as a data frame with the | ||
| # jags output results for each stratification rbinded. | ||
|
|
||
| # Making output a tibble and restructing. | ||
| jags_out <- dplyr::as_tibble(jags_out) |> | ||
| select(!c("Parameter")) |> | ||
| rename("Parameter" = "Parameter_sub") | ||
|
|
||
| if (with_pop_params) { | ||
| # Preparing population parameters | ||
| population_params <- prep_popparams(jags_out) | ||
| population_params <- population_params[, c( | ||
| "Iteration", "Chain", "Parameter", "Iso_type", | ||
| "Stratification", "Population_Parameter", "value" | ||
| )] | ||
|
|
||
| # Taking out population parameters | ||
| jags_out <- ex_popparams(jags_out) | ||
| } | ||
|
|
||
| # Making output a tibble and restructuring. | ||
| jags_out <- jags_out[, c("Iteration", "Chain", "Parameter", "Iso_type", | ||
| "Stratification", "Subject", "value")] | ||
|
Comment on lines
232
to
233
|
||
| current_atts <- attributes(jags_out) | ||
| current_atts <- c(current_atts, mod_atts) | ||
| attributes(jags_out) <- current_atts | ||
| current_atts <- attributes(jags_out) | ||
| # Explicitly build the attribute list in the correct order to ensure that | ||
| # `class` appears immediately after `names` and `row.names`. | ||
| # The dplyr operations above can carry ggmcmc attributes (nChains, etc.) | ||
| # from jags_packed into jags_out, placing `class` at the end. We use | ||
| # mod_atts (named selection from jags_packed) as the authoritative source | ||
| # for the ggmcmc-style metadata attributes. | ||
| new_atts <- list( | ||
| names = current_atts$names, | ||
| row.names = current_atts$row.names, | ||
| class = union("sr_model", current_atts$class), | ||
| nChains = mod_atts$nChains, | ||
| nParameters = mod_atts$nParameters, | ||
| nIterations = mod_atts$nIterations, | ||
| nBurnin = mod_atts$nBurnin, | ||
| nThin = mod_atts$nThin, | ||
| description = mod_atts$description | ||
| ) | ||
| attributes(jags_out) <- new_atts | ||
|
|
||
| # Adding priors | ||
| # Adding population parameters optionally and priors in as attributes | ||
| if (with_pop_params) { | ||
| jags_out <- jags_out |> | ||
| structure(population_params = population_params) | ||
| } | ||
| jags_out <- jags_out |> | ||
| structure("priors" = attributes(priorspec)$used_priors) | ||
| structure(priors = attributes(priorspec)$used_priors) | ||
|
|
||
| # Calculating fitted and residuals | ||
| # Renaming columns using attributes from as_case_data | ||
|
|
@@ -206,7 +271,5 @@ run_mod <- function(data, | |
| jags_out <- jags_out |> | ||
| structure(jags.post = jags_post_final) | ||
| } | ||
| jags_out <- jags_out |> | ||
| structure(class = union("sr_model", class(jags_out))) | ||
| jags_out | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #' @title Excluding population parameters | ||
| #' @author Sam Schildhauer | ||
| #' @description | ||
| #' `ex_popparams` excludes estimated population parameters from final output | ||
| #' [data.frame]. | ||
| #' @param x A [data.frame] with a `Subject` variable. | ||
| #' @returns A filtered [data.frame] excluding population parameters. | ||
| #' @keywords internal | ||
| ex_popparams <- function(x) { | ||
| x <- x |> | ||
| dplyr::filter(!(.data$Subject %in% c("mu.par", "prec.par", "prec.logy"))) | ||
| return(x) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #' @title Parameter recode | ||
| #' @author Sam Schildhauer | ||
| #' @description | ||
| #' `param_recode` recodes character numbers as their corresponding parameter. | ||
| #' @param x A [vector] of character numbers that represent parameters. | ||
| #' @returns A [vector] with recoded values. | ||
| #' @keywords internal | ||
| param_recode <- function(x) { | ||
| dplyr::recode( | ||
| x, | ||
| "1" = "y0", | ||
| "2" = "y1", | ||
| "3" = "t1", | ||
| "4" = "alpha", | ||
| "5" = "shape" | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| #' @title Preparing population parameters | ||
| #' @author Sam Schildhauer | ||
| #' @description | ||
| #' `prep_popparams` filters a [data.frame] to only include population | ||
| #' parameters and renames the `Subject` variable as `Population_Parameter`. | ||
| #' @param x A [data.frame] with a `Subject` variable. | ||
| #' @returns A filtered [data.frame] with the `Subject` variable renamed to | ||
| #' `Population_Parameter`. | ||
| #' @keywords internal | ||
| prep_popparams <- function(x) { | ||
| x <- x |> | ||
| dplyr::filter(.data$Subject %in% c("mu.par", "prec.par", "prec.logy")) |> | ||
| dplyr::rename(Population_Parameter = "Subject") | ||
| return(x) | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.