Skip to content

Commit fb21b67

Browse files
skpr v1.7.1: Add error bars to Monte Carlo eval output if detailedoutput = TRUE
1 parent ceb4e84 commit fb21b67

12 files changed

+91
-17
lines changed

DESCRIPTION

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: skpr
22
Title: Design of Experiments Suite: Generate and Evaluate Optimal Designs
3-
Date: 2024-03-18
4-
Version: 1.7.0
3+
Date: 2024-03-25
4+
Version: 1.7.1
55
Authors@R: c(person("Tyler", "Morgan-Wall", email = "[email protected]", role = c("aut", "cre")),
66
person("George", "Khoury", email = "[email protected]", role = c("aut")))
77
Description: Generates and evaluates D, I, A, Alias, E, T, and G optimal designs. Supports generation and evaluation of blocked and split/split-split/.../N-split plot designs. Includes parametric and Monte Carlo power evaluation functions, and supports calculating power for censored responses. Provides a framework to evaluate power using functions provided in other packages or written by the user. Includes a Shiny graphical user interface that displays the underlying code used to create and evaluate the design to improve ease-of-use and make analyses more reproducible. For details, see Morgan-Wall et al. (2021) <doi:10.18637/jss.v099.i01>.

R/add_ci_bounds_mc_power.R

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#'@title Calculate CI bounds on Monte Carlo
2+
#'
3+
#'@description Calculates CI bounds for Monte Carlo power
4+
#'@return Power data.frame with conf intervals
5+
#'@keywords internal
6+
add_ci_bounds_mc_power = function(power_results, nsim, conf = 0.95) {
7+
get_lcbs = function(power) {
8+
return(unlist(lapply(power, \(x) (binom.test(x*nsim, n = nsim, conf.level = conf)[["conf.int"]][1]))))
9+
}
10+
get_ucbs = function(power) {
11+
return(unlist(lapply(power, \(x) (binom.test(x*nsim, n = nsim, conf.level = conf)[["conf.int"]][2]))))
12+
}
13+
lcb = get_lcbs(power_results[["power"]])
14+
ucb = get_ucbs(power_results[["power"]])
15+
power_results$power_lcb = lcb
16+
power_results$power_ucb = ucb
17+
return(power_results)
18+
}

R/eval_design_custom_mc.R

+20-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
#'fit returned by `fitfunction` must have a method compatable with the car package.
2626
#'@param parameternames Vector of parameter names if the coefficients do not correspond simply to the columns in the model matrix
2727
#'(e.g. coefficients from an MLE fit).
28+
#'@param detailedoutput Default `FALSE`. If `TRUE`, return additional information about evaluation in results.
2829
#'@param advancedoptions Default `NULL`. Named list of advanced options. `advancedoptions$anovatype` specifies the Anova type in the car package (default type `III`),
2930
#'user can change to type `II`). `advancedoptions$anovatest` specifies the test statistic if the user does not want a `Wald` test--other options are likelyhood-ratio `LR` and F-test `F`.
3031
#'`advancedoptions$progressBarUpdater` is a function called in non-parallel simulations that can be used to update external progress bar.`advancedoptions$GUI` turns off some warning messages when in the GUI.
31-
#'If `advancedoptions$save_simulated_responses = TRUE`, the dataframe will have an attribute `simulated_responses` that contains the simulated responses from the power evaluation.
32+
#'If `advancedoptions$save_simulated_responses = TRUE`, the dataframe will have an attribute `simulated_responses` that contains the simulated responses from the power evaluation. `advancedoptions$ci_error_conf` will
33+
#'set the confidence level for power intervals, which are printed when `detailedoutput = TRUE`.
3234
#'@param anticoef The anticipated coefficients for calculating the power. If missing, coefficients will be
3335
#'automatically generated based on \code{effectsize}.
3436
#'@param effectsize The signal-to-noise ratio. Default 2. For a gaussian model, and for
@@ -102,7 +104,7 @@
102104
eval_design_custom_mc = function(design, model = NULL, alpha = 0.05,
103105
nsim, rfunction, fitfunction, pvalfunction,
104106
anticoef, effectsize = 2, contrasts = contr.sum,
105-
coef_function = coef, calceffect = FALSE,
107+
coef_function = coef, calceffect = FALSE, detailedoutput = FALSE,
106108
parameternames = NULL, advancedoptions = NULL, progress = TRUE,
107109
parallel = FALSE, parallel_pkgs = NULL, ...) {
108110
if (!is.null(advancedoptions)) {
@@ -135,6 +137,9 @@ eval_design_custom_mc = function(design, model = NULL, alpha = 0.05,
135137
progress = getOption("skpr_progress")
136138
}
137139

140+
if(is.null(advancedoptions$ci_error_conf)) {
141+
advancedoptions$ci_error_conf = 0.95
142+
}
138143
if (!is.null(advancedoptions$anovatype)) {
139144
anovatype = advancedoptions$anovatype
140145
} else {
@@ -351,6 +356,19 @@ eval_design_custom_mc = function(design, model = NULL, alpha = 0.05,
351356
attr(power_final, "runmatrix") = RunMatrixReduced
352357
attr(power_final, "anticoef") = anticoef
353358

359+
if (detailedoutput) {
360+
if (nrow(power_final) != length(anticoef)){
361+
power_final$anticoef = c(rep(NA, nrow(power_final) - length(anticoef)), anticoef)
362+
} else {
363+
power_final$anticoef = anticoef
364+
}
365+
power_final$alpha = alpha
366+
power_final$trials = nrow(run_matrix_processed)
367+
power_final$nsim = nsim
368+
power_final = add_ci_bounds_mc_power(power_final, nsim = nsim, conf = advancedoptions$ci_error_conf)
369+
attr(power_final, "mc.conf.int") = advancedoptions$ci_error_conf
370+
}
371+
354372
if(!inherits(power_final,"skpr_eval_output")) {
355373
class(power_final) = c("skpr_eval_output", class(power_final))
356374
}

R/eval_design_mc.R

+7-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@
4949
#'@param advancedoptions Default `NULL`. Named list of advanced options. `advancedoptions$anovatype` specifies the Anova type in the car package (default type `III`),
5050
#'user can change to type `II`). `advancedoptions$anovatest` specifies the test statistic if the user does not want a `Wald` test--other options are likelyhood-ratio `LR` and F-test `F`.
5151
#'`advancedoptions$progressBarUpdater` is a function called in non-parallel simulations that can be used to update external progress bar.`advancedoptions$GUI` turns off some warning messages when in the GUI.
52-
#'If `advancedoptions$save_simulated_responses = TRUE`, the dataframe will have an attribute `simulated_responses` that contains the simulated responses from the power evaluation.
52+
#'If `advancedoptions$save_simulated_responses = TRUE`, the dataframe will have an attribute `simulated_responses` that contains the simulated responses from the power evaluation. `advancedoptions$ci_error_conf` will
53+
#'set the confidence level for power intervals, which are printed when `detailedoutput = TRUE`.
5354
#'@param parallel Default `FALSE`. If `TRUE`, the Monte Carlo power calculation will use all but one of the available cores. If the user wants to set the number of cores manually, they can do this by setting `options("cores")` to the desired number (e.g. `options("cores" = parallel::detectCores())`).
5455
#' NOTE: If you have installed BLAS libraries that include multicore support (e.g. Intel MKL that comes with Microsoft R Open), turning on parallel could result in reduced performance.
5556
#'@param ... Additional arguments.
@@ -322,6 +323,9 @@ eval_design_mc = function(design, model = NULL, alpha = 0.05,
322323
}
323324
aliaspower = advancedoptions$aliaspower
324325
}
326+
if(is.null(advancedoptions$ci_error_conf)) {
327+
advancedoptions$ci_error_conf = 0.95
328+
}
325329
alpha_adjust = FALSE
326330
if (adjust_alpha_inflation) {
327331
alpha_adjust = TRUE
@@ -966,6 +970,8 @@ eval_design_mc = function(design, model = NULL, alpha = 0.05,
966970
} else {
967971
retval$error_adjusted_alpha = alpha_parameter
968972
}
973+
retval = add_ci_bounds_mc_power(retval, nsim = nsim, conf = advancedoptions$ci_error_conf)
974+
attr(retval, "mc.conf.int") = advancedoptions$ci_error_conf
969975
}
970976

971977
colnames(estimates) = parameter_names

R/eval_design_survival_mc.R

+14-6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
#' NOTE: If you have installed BLAS libraries that include multicore support (e.g. Intel MKL that comes with Microsoft R Open), turning on parallel could result in reduced performance.
3535
#'@param detailedoutput Default `FALSE`. If `TRUE`, return additional information about evaluation in results.
3636
#'@param progress Default `TRUE`. Whether to include a progress bar.
37-
#'@param advancedoptions Default NULL. Named list of advanced options. Pass `progressBarUpdater` to include function called in non-parallel simulations that can be used to update external progress bar.
37+
#'@param advancedoptions Default `NULL`. Named list of advanced options. Pass `progressBarUpdater` to include function called in non-parallel simulations that can be used to update external progress bar.
38+
#'`advancedoptions$ci_error_conf` will set the confidence level for power intervals, which are printed when `detailedoutput = TRUE`.
3839
#'@param ... Any additional arguments to be passed into the \code{survreg} function during fitting.
3940
#'@return A data frame consisting of the parameters and their powers. The parameter estimates from the simulations are
4041
#'stored in the 'estimates' attribute. The 'modelmatrix' attribute contains the model matrix and the encoding used for
@@ -161,6 +162,9 @@ eval_design_survival_mc = function(design, model = NULL, alpha = 0.05,
161162
advancedoptions$GUI = FALSE
162163
progressBarUpdater = NULL
163164
}
165+
if(is.null(advancedoptions$ci_error_conf)) {
166+
advancedoptions$ci_error_conf = 0.95
167+
}
164168
if (attr(terms.formula(model, data = design), "intercept") == 1) {
165169
nointercept = FALSE
166170
} else {
@@ -304,7 +308,7 @@ eval_design_survival_mc = function(design, model = NULL, alpha = 0.05,
304308
)
305309

306310
#determine whether beta[i] is significant. If so, increment nsignificant
307-
pvals = extractPvalues(fit)[1:ncol(ModelMatrix)]
311+
pvals = extractPvalues(fit)[seq_len(ncol(ModelMatrix))]
308312
pvals = pvals[order(factor(names(pvals), levels = parameter_names))]
309313
pvals[is.na(pvals)] = 1
310314
stopifnot(all(names(pvals) == parameter_names))
@@ -360,7 +364,7 @@ eval_design_survival_mc = function(design, model = NULL, alpha = 0.05,
360364
)
361365

362366
#determine whether beta[i] is significant. If so, increment nsignificant
363-
pvals = extractPvalues(fit)[1:ncol(ModelMatrix)]
367+
pvals = extractPvalues(fit)[seq_len(ncol(ModelMatrix))]
364368
pvals = pvals[order(factor(names(pvals), levels = parameter_names))]
365369
stopifnot(all(names(pvals) == parameter_names))
366370
pvals[is.na(pvals)] = 1
@@ -386,13 +390,17 @@ eval_design_survival_mc = function(design, model = NULL, alpha = 0.05,
386390
attr(retval, "alpha") = alpha
387391
attr(retval, "runmatrix") = RunMatrixReduced
388392

389-
390393
if (detailedoutput) {
391-
retval$anticoef = anticoef
394+
if (nrow(retval) != length(anticoef)){
395+
retval$anticoef = c(rep(NA, nrow(retval) - length(anticoef)), anticoef)
396+
} else {
397+
retval$anticoef = anticoef
398+
}
392399
retval$alpha = alpha
393-
retval$distribution = distribution
394400
retval$trials = nrow(run_matrix_processed)
395401
retval$nsim = nsim
402+
retval = add_ci_bounds_mc_power(retval, nsim = nsim, conf = advancedoptions$ci_error_conf)
403+
attr(retval, "mc.conf.int") = advancedoptions$ci_error_conf
396404
}
397405
if(!inherits(retval,"skpr_eval_output")) {
398406
class(retval) = c("skpr_eval_output", class(retval))

R/methods.R

+5-2
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ print.skpr_eval_output = function(x, ...) {
8080
}
8181
if (!is.null(attr(x,"z.matrix.list")) && blocking) {
8282
number_blocks = unlist(lapply(attr(x,"z.matrix.list"),ncol))
83-
block_str = paste(paste("Level ", 1:length(number_blocks), ": ", number_blocks, sep = ""),
83+
block_str = paste(paste("Level ", seq_len(length(number_blocks)), ": ", number_blocks, sep = ""),
8484
collapse=", ")
8585
cat(generate_text("Number of Blocks",block_str), sep = "\n")
8686
}
8787
if (!is.null(attr(x,"varianceratios")) && blocking) {
8888
vr = attr(x,"varianceratios")
89-
vr_str = paste(paste("Level ", 1:length(vr), ": ",as.character(vr), sep="", collapse=", "))
89+
vr_str = paste(paste("Level ", seq_len(length(vr)), ": ",as.character(vr), sep="", collapse=", "))
9090
cat(generate_text("Variance Ratios ",vr_str), sep = "\n")
9191
}
9292
if(!is.null(attr(x, "contrast_string"))) {
@@ -102,6 +102,9 @@ print.skpr_eval_output = function(x, ...) {
102102
cat(generate_text("Effect Analysis Method", attr(x, "effect_analysis_method_string")),sep="\n")
103103
}
104104
}
105+
if(!is.null(attr(x, "mc.conf.int"))) {
106+
cat(generate_text("MC Power CI Confidence", sprintf("%0.0f%%",100*attr(x, "mc.conf.int"))),sep="\n")
107+
}
105108
}
106109

107110
#'@title Print evaluation information

R/skprGUI.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -2428,7 +2428,7 @@ skprGUI = function(browser = FALSE, return_app = FALSE, multiuser = FALSE, progr
24282428

24292429
filter_power_results = function(results) {
24302430
col_results = colnames(results)
2431-
results[, !col_results %in% c("glmfamily", "trials", "nsim", "blocking")]
2431+
results[, !col_results %in% c("glmfamily", "trials", "nsim", "blocking" ,"power_ucb", "power_lcb")]
24322432
}
24332433

24342434
output$powerresults = gt::render_gt( {

man/add_ci_bounds_mc_power.Rd

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/eval_design_custom_mc.Rd

+5-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/eval_design_mc.Rd

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/eval_design_survival_mc.Rd

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/Rplots.pdf

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)