Skip to content

Commit 4a42868

Browse files
author
NightlordTW
committed
Update hierarchical test & vignettes
1 parent 10f251e commit 4a42868

16 files changed

+1056
-206
lines changed

R/RcppExports.R

Lines changed: 147 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -293,16 +293,106 @@ run_simulations_par <- function(nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, ue
293293
.Call(`_SimTOST_run_simulations_par`, nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, uequi_tol, alpha, dropout, typey, adseq, k, arm_seed_T, arm_seed_R, ctype, lognorm, TART, TARR, vareq)
294294
}
295295

296-
#' @title Run Simulations for a 2x2 Crossover Design
296+
#' @title Run Simulations for a Parallel Design with Difference of Means (DOM) test
297297
#'
298298
#' @description
299-
#' This function simulates a 2x2 crossover study design across multiple iterations (`nsim`).
300-
#' It evaluates equivalence testing for multiple endpoints using either the
301-
#' Difference of Means (DOM) or Ratio of Means (ROM) approach.
299+
#' This function simulates a parallel-group trial across multiple iterations.
300+
#' It evaluates equivalence across multiple endpoints using the
301+
#' Difference of Means (DOM) test.
302+
#'
303+
#' @param nsim Integer. The number of simulations to run.
304+
#' @param n Integer. The sample size per arm (before dropout).
305+
#' @param muT arma::vec. Mean vector for the treatment arm.
306+
#' @param muR arma::vec. Mean vector for the reference arm.
307+
#' @param SigmaT arma::mat. Covariance matrix for the treatment arm.
308+
#' @param SigmaR arma::mat. Covariance matrix for the reference arm.
309+
#' @param lequi_tol arma::rowvec. Lower equivalence thresholds for each endpoint.
310+
#' @param uequi_tol arma::rowvec. Upper equivalence thresholds for each endpoint.
311+
#' @param alpha arma::rowvec. Significance level (α) for each endpoint.
312+
#' @param dropout arma::vec. Dropout rates for each arm (T, R).
313+
#' @param typey Integer vector indicating the classification of each endpoint, where `1` corresponds to a primary endpoint and `2` corresponds to a secondary endpoint.
314+
#' @param adseq Boolean. If `TRUE`, applies sequential (hierarchical) testing.
315+
#' @param k Integer. Minimum number of endpoints required for equivalence.
316+
#' @param arm_seed_T arma::ivec. Random seed vector for the treatment group (one per simulation).
317+
#' @param arm_seed_R arma::ivec. Random seed vector for the reference group (one per simulation).
318+
#' @param TART Double. Treatment allocation ratio (proportion of subjects in treatment arm).
319+
#' @param TARR Double. Reference allocation ratio (proportion of subjects in reference arm).
320+
#' @param vareq Boolean. If `TRUE`, assumes equal variances across treatment and reference groups.
321+
#'
322+
#' @details
323+
#' Equivalence testing uses either the Difference of Means (DOM) test,
324+
#' applying predefined equivalence thresholds and significance levels. When hierarchical testing (`adseq`)
325+
#' is enabled, all primary endpoints must demonstrate equivalence before secondary endpoints are evaluated.
326+
#' Dropout rates are incorporated into the sample size calculation to ensure proper adjustment.
327+
#' Randomization is controlled through separate random seeds for the treatment and reference groups,
328+
#' enhancing reproducibility.
329+
#'
330+
#' @return
331+
#' The function returns an arma::mat storing simulation results row-wise for consistency
332+
#' with R's output format. The first row (`totaly`) contains the overall equivalence decision
333+
#' (1 for success, 0 for failure). The subsequent rows include equivalence deicisons for each endpoint,
334+
#' mean estimates for both treatment and reference groups, and corresponding standard deviations.
335+
#'
336+
#' @author Thomas Debray \email{[email protected]}
337+
#' @export
338+
run_simulations_par_dom <- function(nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, uequi_tol, alpha, dropout, typey, adseq, k, arm_seed_T, arm_seed_R, TART, TARR, vareq) {
339+
.Call(`_SimTOST_run_simulations_par_dom`, nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, uequi_tol, alpha, dropout, typey, adseq, k, arm_seed_T, arm_seed_R, TART, TARR, vareq)
340+
}
341+
342+
#' @title Run Simulations for a Parallel Design with Ratio of Means (ROM) test
343+
#'
344+
#' @description
345+
#' This function simulates a parallel-group trial across multiple iterations.
346+
#' It evaluates equivalence across multiple endpoints using the
347+
#' Ratio of Means (ROM) test.
348+
#'
349+
#' @param nsim Integer. The number of simulations to run.
350+
#' @param n Integer. The sample size per arm (before dropout).
351+
#' @param muT arma::vec. Mean vector for the treatment arm.
352+
#' @param muR arma::vec. Mean vector for the reference arm.
353+
#' @param SigmaT arma::mat. Covariance matrix for the treatment arm.
354+
#' @param SigmaR arma::mat. Covariance matrix for the reference arm.
355+
#' @param lequi_tol arma::rowvec. Lower equivalence thresholds for each endpoint.
356+
#' @param uequi_tol arma::rowvec. Upper equivalence thresholds for each endpoint.
357+
#' @param alpha arma::rowvec. Significance level (α) for each endpoint.
358+
#' @param dropout arma::vec. Dropout rates for each arm (T, R).
359+
#' @param typey Integer vector indicating the classification of each endpoint, where `1` corresponds to a primary endpoint and `2` corresponds to a secondary endpoint.
360+
#' @param adseq Boolean. If `TRUE`, applies sequential (hierarchical) testing.
361+
#' @param k Integer. Minimum number of endpoints required for equivalence.
362+
#' @param arm_seed_T arma::ivec. Random seed vector for the treatment group (one per simulation).
363+
#' @param arm_seed_R arma::ivec. Random seed vector for the reference group (one per simulation).
364+
#' @param TART Double. Treatment allocation ratio (proportion of subjects in treatment arm).
365+
#' @param TARR Double. Reference allocation ratio (proportion of subjects in reference arm).
366+
#' @param vareq Boolean. If `TRUE`, assumes equal variances across treatment and reference groups.
367+
#'
368+
#' @details
369+
#' Equivalence testing uses either the Ratio of Means (ROM) test,
370+
#' applying predefined equivalence thresholds and significance levels. When hierarchical testing (`adseq`)
371+
#' is enabled, all primary endpoints must demonstrate equivalence before secondary endpoints are evaluated.
372+
#' Dropout rates are incorporated into the sample size calculation to ensure proper adjustment.
373+
#' Randomization is controlled through separate random seeds for the treatment and reference groups,
374+
#' enhancing reproducibility.
375+
#'
376+
#' @return
377+
#' The function returns an arma::mat storing simulation results row-wise for consistency
378+
#' with R's output format. The first row (`totaly`) contains the overall equivalence decision
379+
#' (1 for success, 0 for failure). The subsequent rows include equivalence deicisons for each endpoint,
380+
#' mean estimates for both treatment and reference groups, and corresponding standard deviations.
381+
#'
382+
#' @author Thomas Debray \email{[email protected]}
383+
#' @export
384+
run_simulations_par_rom <- function(nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, uequi_tol, alpha, dropout, typey, adseq, k, arm_seed_T, arm_seed_R, TART, TARR, vareq) {
385+
.Call(`_SimTOST_run_simulations_par_rom`, nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, uequi_tol, alpha, dropout, typey, adseq, k, arm_seed_T, arm_seed_R, TART, TARR, vareq)
386+
}
387+
388+
#' @title Run Simulations for a 2x2 Crossover Design with Difference of Means (DOM) test
389+
#'
390+
#' @description
391+
#' This function simulates a 2x2 crossover trial across multiple iterations.
392+
#' It evaluates equivalence across multiple endpoints using the
393+
#' Difference of Means (DOM) test.
302394
#'
303395
#' @param nsim Integer. The number of simulations to run.
304-
#' @param ctype Character string. Testing method (`"DOM"` for Difference of Means, `"ROM"` for Ratio of Means).
305-
#' @param lognorm Boolean. If `TRUE`, assumes log-normal distribution for endpoints.
306396
#' @param n Integer. The sample size per period.
307397
#' @param muT Numeric vector. Mean outcomes for the active treatment.
308398
#' @param muR Numeric vector. Mean outcomes for the reference treatment.
@@ -320,7 +410,7 @@ run_simulations_par <- function(nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, ue
320410
#' @param arm_seed Integer vector. Random seed for each simulation.
321411
#'
322412
#' @details
323-
#' This function performs equivalence testing using either the Difference of Means (DOM) or Ratio of Means (ROM) approach.
413+
#' This function evaluates equivalence using either the Difference of Means (DOM) test.
324414
#' Equivalence is determined based on predefined lower (`lequi_tol`) and upper (`uequi_tol`) equivalence thresholds,
325415
#' and hypothesis testing is conducted at the specified significance level (`alpha`).
326416
#' If `adseq` is `TRUE`, primary endpoints must establish equivalence before secondary endpoints are evaluated.
@@ -332,13 +422,60 @@ run_simulations_par <- function(nsim, n, muT, muR, SigmaT, SigmaR, lequi_tol, ue
332422
#' @return
333423
#' A numeric matrix where each column stores simulation results:
334424
#' The first row (`totaly`) represents the overall equivalence decision (1 = success, 0 = failure).
335-
#' Subsequent rows contain p-values for equivalence testing per endpoint (`E1, E2, ...`),
425+
#' Subsequent rows contain equivalence decisions per endpoint (`E1, E2, ...`),
336426
#' mean estimates for the treatment group (`mu_E1_T, mu_E2_T, ...`), mean estimates for the reference group (`mu_E1_R, mu_E2_R, ...`),
337427
#' standard deviations for treatment (`sd_E1_T, sd_E2_T, ...`), and standard deviations for reference (`sd_E1_R, sd_E2_R, ...`).
338428
#'
339429
#' @author Thomas Debray \email{[email protected]}
340430
#' @export
341-
run_simulations_2x2 <- function(nsim, ctype, lognorm, n, muT, muR, SigmaW, lequi_tol, uequi_tol, alpha, sigmaB, dropout, Eper, Eco, typey, adseq, k, arm_seed) {
342-
.Call(`_SimTOST_run_simulations_2x2`, nsim, ctype, lognorm, n, muT, muR, SigmaW, lequi_tol, uequi_tol, alpha, sigmaB, dropout, Eper, Eco, typey, adseq, k, arm_seed)
431+
run_simulations_2x2_dom <- function(nsim, n, muT, muR, SigmaW, lequi_tol, uequi_tol, alpha, sigmaB, dropout, Eper, Eco, typey, adseq, k, arm_seed) {
432+
.Call(`_SimTOST_run_simulations_2x2_dom`, nsim, n, muT, muR, SigmaW, lequi_tol, uequi_tol, alpha, sigmaB, dropout, Eper, Eco, typey, adseq, k, arm_seed)
433+
}
434+
435+
#' @title Run Simulations for a 2x2 Crossover Design with Ratio of Means (ROM) test
436+
#'
437+
#' @description
438+
#' This function simulates a 2x2 crossover trial across multiple iterations.
439+
#' It evaluates equivalence across multiple endpoints using the
440+
#' Ratio of Means (ROM) test.
441+
#'
442+
#' @param nsim Integer. The number of simulations to run.
443+
#' @param n Integer. The sample size per period.
444+
#' @param muT Numeric vector. Mean outcomes for the active treatment.
445+
#' @param muR Numeric vector. Mean outcomes for the reference treatment.
446+
#' @param SigmaW Numeric matrix. Within-subject covariance matrix for endpoints.
447+
#' @param lequi_tol Numeric vector. Lower equivalence thresholds for each endpoint.
448+
#' @param uequi_tol Numeric vector. Upper equivalence thresholds for each endpoint.
449+
#' @param alpha Numeric vector. Significance levels for hypothesis testing across endpoints.
450+
#' @param sigmaB Numeric. Between-subject variance for the crossover model.
451+
#' @param dropout Numeric vector of size 2. Dropout rates for each sequence.
452+
#' @param Eper Numeric vector. Expected period effects for each sequence.
453+
#' @param Eco Numeric vector. Expected carryover effects for each sequence.
454+
#' @param typey Integer vector indicating the classification of each endpoint, where `1` corresponds to a primary endpoint and `2` corresponds to a secondary endpoint.
455+
#' @param adseq Logical. If `TRUE`, applies sequential (hierarchical) testing.
456+
#' @param k Integer. Minimum number of endpoints required for equivalence.
457+
#' @param arm_seed Integer vector. Random seed for each simulation.
458+
#'
459+
#' @details
460+
#' This function evaluates equivalence using either the Ratio of Means (ROM) test.
461+
#' Equivalence is determined based on predefined lower (`lequi_tol`) and upper (`uequi_tol`) equivalence thresholds,
462+
#' and hypothesis testing is conducted at the specified significance level (`alpha`).
463+
#' If `adseq` is `TRUE`, primary endpoints must establish equivalence before secondary endpoints are evaluated.
464+
#' The sample size per period is adjusted based on dropout rates, ensuring valid study conclusions.
465+
#' The simulation incorporates within-subject correlation using `SigmaW` and accounts for between-subject variance with `sigmaB`.
466+
#' Expected period effects (`Eper`) and carryover effects (`Eco`) are included in the model.
467+
#' A fixed random seed (`arm_seed`) is used to ensure reproducibility across simulations.
468+
#'
469+
#' @return
470+
#' A numeric matrix where each column stores simulation results:
471+
#' The first row (`totaly`) represents the overall equivalence decision (1 = success, 0 = failure).
472+
#' Subsequent rows contain equivalence decisions per endpoint (`E1, E2, ...`),
473+
#' mean estimates for the treatment group (`mu_E1_T, mu_E2_T, ...`), mean estimates for the reference group (`mu_E1_R, mu_E2_R, ...`),
474+
#' standard deviations for treatment (`sd_E1_T, sd_E2_T, ...`), and standard deviations for reference (`sd_E1_R, sd_E2_R, ...`).
475+
#'
476+
#' @author Thomas Debray \email{[email protected]}
477+
#' @export
478+
run_simulations_2x2_rom <- function(nsim, n, muT, muR, SigmaW, lequi_tol, uequi_tol, alpha, sigmaB, dropout, Eper, Eco, typey, adseq, k, arm_seed) {
479+
.Call(`_SimTOST_run_simulations_2x2_rom`, nsim, n, muT, muR, SigmaW, lequi_tol, uequi_tol, alpha, sigmaB, dropout, Eper, Eco, typey, adseq, k, arm_seed)
343480
}
344481

R/SampleSize.R

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,20 +229,24 @@ sampleSize <- function(mu_list, varcov_list = NA, sigma_list = NA, cor_mat = NA,
229229

230230
# Define weights according to type of endpoint,i.e. primary, secondary
231231

232-
if (any(is.na(type_y)) | length(type_y) != length(uynames)) {
233-
type_y <- rep(1,length(uynames))
234-
}
235-
236-
names(type_y) <- uynames
232+
if (adjust != "seq" | any(is.na(type_y)) | length(type_y) != length(uynames)) {
233+
type_y <- -1
234+
weight_seq <- rep(1, length(uynames))
235+
} else {
236+
names(type_y) <- uynames
237237

238+
# Count number of secondary endpoints (elements equal to 2 in type_y)
239+
num_secondary_endpoints <- sum(type_y == 2)
238240

239-
weight <- 1/table(type_y)
240-
weight_seq <- type_y
241+
# Initialize weight vector with 1s
242+
weight_seq <- rep(1, length(type_y))
241243

242-
for (x in unique(type_y)) {
243-
weight_seq[weight_seq == x] <- weight[x]
244+
# Assign 1 / num_secondary_endpoints to secondary endpoints
245+
if (num_secondary_endpoints > 0) {
246+
weight_seq[type_y == 2] <- 1 / num_secondary_endpoints
247+
}
248+
names(weight_seq) <- uynames
244249
}
245-
names(weight_seq) <- uynames
246250

247251
#if (len_mu[[1]] == 1){
248252
# mu_list <- lapply(mu_list,FUN = function(x){array(unlist(x))})

0 commit comments

Comments
 (0)