diff --git a/R/wlr.R b/R/wlr.R index 4ac5abe9..5e124763 100644 --- a/R/wlr.R +++ b/R/wlr.R @@ -38,7 +38,7 @@ #' + If not, simtrial takes the empirical randomization ratio. #' @param formula A formula to specify the columns that contain the #' time-to-event, event, treatment, and stratum variables. Only used by the -#' default S3 method because the other classes aleady have the required column +#' default S3 method because the other classes already have the required column #' names. For stratified designs, the formula should have the form `Surv(tte, #' event) ~ treatment + strata(stratum)`, where `tte`, `event`, `treatment`, #' and `stratum` are the column names from `data` with the time-to-event @@ -102,14 +102,14 @@ #' # ---------------------- # #' x <- sim_pw_surv(n = 200) |> cut_data_by_event(100) #' -#' # Example 1A: WLR test with FH wights +#' # Example 1A: WLR test with FH weights #' x |> wlr(weight = fh(rho = 0, gamma = 0.5)) #' x |> wlr(weight = fh(rho = 0, gamma = 0.5), return_variance = TRUE) #' -#' # Example 1B: WLR test with MB wights +#' # Example 1B: WLR test with MB weights #' x |> wlr(weight = mb(delay = 4, w_max = 2)) #' -#' # Example 1C: WLR test with early zero wights +#' # Example 1C: WLR test with early zero weights #' x |> wlr(weight = early_zero(early_period = 4)) #' #' # Example 1D @@ -137,7 +137,7 @@ #' counting_process(arm = "experimental") |> #' wlr(weight = fh(rho = 0, gamma = 0.5), ratio = 2) #' -#' # If users don't provide the randomization ratio, we will calculate the emperical ratio +#' # If users don't provide the randomization ratio, we will calculate the empirical ratio #' x |> wlr(weight = fh(rho = 0, gamma = 0.5)) #' #' x |> diff --git a/man/wlr.Rd b/man/wlr.Rd index 20585f03..db6884e2 100644 --- a/man/wlr.Rd +++ b/man/wlr.Rd @@ -46,7 +46,7 @@ there is no need to input the \code{ratio}, as simtrial gets the \code{ratio} vi \item{formula}{A formula to specify the columns that contain the time-to-event, event, treatment, and stratum variables. Only used by the -default S3 method because the other classes aleady have the required column +default S3 method because the other classes already have the required column names. For stratified designs, the formula should have the form \code{Surv(tte, event) ~ treatment + strata(stratum)}, where \code{tte}, \code{event}, \code{treatment}, and \code{stratum} are the column names from \code{data} with the time-to-event measurement, event status, treatment group, and stratum, respectively. For @@ -110,14 +110,14 @@ The stratified Fleming-Harrington weighted logrank test is then computed as: # ---------------------- # x <- sim_pw_surv(n = 200) |> cut_data_by_event(100) -# Example 1A: WLR test with FH wights +# Example 1A: WLR test with FH weights x |> wlr(weight = fh(rho = 0, gamma = 0.5)) x |> wlr(weight = fh(rho = 0, gamma = 0.5), return_variance = TRUE) -# Example 1B: WLR test with MB wights +# Example 1B: WLR test with MB weights x |> wlr(weight = mb(delay = 4, w_max = 2)) -# Example 1C: WLR test with early zero wights +# Example 1C: WLR test with early zero weights x |> wlr(weight = early_zero(early_period = 4)) # Example 1D @@ -145,7 +145,7 @@ x |> counting_process(arm = "experimental") |> wlr(weight = fh(rho = 0, gamma = 0.5), ratio = 2) -# If users don't provide the randomization ratio, we will calculate the emperical ratio +# If users don't provide the randomization ratio, we will calculate the empirical ratio x |> wlr(weight = fh(rho = 0, gamma = 0.5)) x |> diff --git a/tests/testthat/test-independent_test_simfix2simpwsurv.R b/tests/testthat/test-independent_test_simfix2simpwsurv.R index a1656952..14cf699d 100644 --- a/tests/testthat/test-independent_test_simfix2simpwsurv.R +++ b/tests/testthat/test-independent_test_simfix2simpwsurv.R @@ -87,7 +87,7 @@ test_that("fail_rate must be smaller than 1 and positive", { expect_gt(min(fail_rate$fail_rate), 0) }) -test_that("hr must be postiive", { +test_that("hr must be positive", { res <- test_simfix2simpwsurv() fail_rate <- res$fail_rate diff --git a/vignettes/sim_gs_design_simple.Rmd b/vignettes/sim_gs_design_simple.Rmd index d0c4a3b5..632edbc1 100644 --- a/vignettes/sim_gs_design_simple.Rmd +++ b/vignettes/sim_gs_design_simple.Rmd @@ -26,31 +26,31 @@ The `sim_gs_n()` function simulates group sequential designs with fixed sample s The process for simulating via `sim_gs_n()` is outlined in Steps 1 to 3 below. -# Step 1: Define design paramaters +# Step 1: Define design parameters -To run simulations for a group sequential design, several design characteristics are required. -The following code creates a design for an unstratified 2-arm trial with equal randomization. -Enrollment is targeted to last for 12 months at a constant enrollment rate. +To run simulations for a group sequential design, several design characteristics are required. +The following code creates a design for an unstratified 2-arm trial with equal randomization. +Enrollment is targeted to last for 12 months at a constant enrollment rate. The control arm is specified as exponential with a median of 10 months. -The experimental arm distribution has a piecewise exponential distribution with a delay of 3 months with no benefit relative to control (HR = 1) followed by a hazard ratio of 0.6 thereafter. -Additionally, there is an exponential dropout rate of 0.001 per month (or unit of time). +The experimental arm distribution has a piecewise exponential distribution with a delay of 3 months with no benefit relative to control (HR = 1) followed by a hazard ratio of 0.6 thereafter. +Additionally, there is an exponential dropout rate of 0.001 per month (or unit of time). The set up of these parameters is similar to the vignette [Simulate Fixed Designs with Ease via sim_fixed_n](https://merck.github.io/simtrial/articles/sim_fixed_design_simple.html). -The total sample size is derived for 90\% power. +The total sample size is derived for 90\% power. ```{r} stratum <- data.frame(stratum = "All", p = 1) block <- rep(c("experimental", "control"), 2) -# enrollment rate will be updated later, +# enrollment rate will be updated later, # multiplied by a constant to get targeted power enroll_rate <- data.frame(stratum = "All", rate = 1, duration = 12) fail_rate <- data.frame(stratum = "All", - duration = c(3, Inf), fail_rate = log(2) / 10, + duration = c(3, Inf), fail_rate = log(2) / 10, hr = c(1, 0.6), dropout_rate = 0.001) # Derive design using the average hazard ratio method x <- gs_design_ahr(enroll_rate = enroll_rate, fail_rate = fail_rate, analysis_time = c(12, 24, 36), alpha = 0.025, beta = 0.1, # spending function for upper bound - upper = gs_spending_bound, + upper = gs_spending_bound, upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025), # Fixed lower bound lower = gs_b, @@ -76,8 +76,8 @@ enroll_rate ``` -There are additional parameters required for a group sequential design simulation as demonstrated below. -One is the testing method. We focus on logrank here. +There are additional parameters required for a group sequential design simulation as demonstrated below. +One is the testing method. We focus on logrank here. Users can change these to other tests of interest; in comments below we demonstrate logrank and modestly weighted logrank test (@MagirrBurman) and Fleming-Harrington (@FH1982) tests; how to set up group sequential designs for these alternate tests is beyond the scope of this article. More testing methods are available at [reference page of `simtrial`](https://merck.github.io/simtrial/reference/index.html#compute-p-values-test-statistics). @@ -91,14 +91,14 @@ test <- wlr # weight <- fh(rho = 0, gamma = 0.5) ``` -The final step is to specify how when data is cut off for each analysis in the group sequential design. -The `create_cut()` function includes 5 options for the analysis cutoff: +The final step is to specify how when data is cut off for each analysis in the group sequential design. +The `create_cut()` function includes 5 options for the analysis cutoff: -(1) planned calendar time, -(2) targeted events, -(3) maximum time extension to reach targeted events, +(1) planned calendar time, +(2) targeted events, +(3) maximum time extension to reach targeted events, (4) planned minimum time after the previous analysis, and -(5) minimal follow-up time after specified enrollment fraction. +(5) minimal follow-up time after specified enrollment fraction. More details and examples are available at the [help page](https://merck.github.io/simtrial/reference/get_analysis_date.html). @@ -112,28 +112,28 @@ fa_cut <- create_cut(target_event_overall = event[3]) cut <- list(ia1 = ia1_cut, ia2 = ia2_cut, fa = fa_cut) ``` -Users can set more complex cutting. For example, +Users can set more complex cutting. For example, -- The first interim analysis occurs at the targeted IA 1 analyusis time or when at least the IA 1 targeted events are observed, which is later. +- The first interim analysis occurs at the targeted IA 1 analyusis time or when at least the IA 1 targeted events are observed, which is later. However, if the target number of events is not reached, we will wait a maximum of 16 months from start of enrollment. - The second interim analysis is targeted to take place at the targeted time or targeted events for IA 2, whichever is later. Additionally, this interim analysis will be scheduled at least 10 months after the first interim analysis, but no later than 28 months from start of enrollment. - The final analysis is set for the targeted final analysis time or targeted events at the final analysis, whichever is later. -It must be at least 6 months after IA 2. +It must be at least 6 months after IA 2. -**Please keep in mind that if the cut is not event-driven, boundary updates are necessary; this is not covered here.** -You can find more information about [the boundary updates in the boundary update vignette](https://merck.github.io/simtrial/articles/sim_fixed_design_simple.html). +**Please keep in mind that if the cut is not event-driven, boundary updates are necessary; this is not covered here.** +You can find more information about [the boundary updates in the boundary update vignette](https://merck.github.io/simtrial/articles/sim_fixed_design_simple.html). In this vignette, we use the event-driven cut from above for illustrative purposes. ```{r, eval=FALSE} ia1_cut <- create_cut( - planned_calendar_time = round(x$analysis$time[1]), + planned_calendar_time = round(x$analysis$time[1]), target_event_overall = x$analysis$event[1], max_extension_for_target_event = 16) ia2_cut <- create_cut( planned_calendar_time = round(x$analysis$time[2]), target_event_overall = x$analysis$event[2], - min_time_after_previous_analysis = 10, + min_time_after_previous_analysis = 10, max_extension_for_target_event = 28) fa_cut <- create_cut( @@ -146,7 +146,7 @@ cut <- list(ia1 = ia1_cut, ia2 = ia2_cut, fa = fa_cut) # Step 2: Run `sim_gs_n()` -Now that we have set up the design characteristics in Step 1, we can proceed to run `sim_gs_n()` for a specified number of simulations. +Now that we have set up the design characteristics in Step 1, we can proceed to run `sim_gs_n()` for a specified number of simulations. This function automatically utilizes a parallel computing backend, which helps reduce the running time. ```{r, message=FALSE} @@ -159,9 +159,9 @@ sim_res <- sim_gs_n( ``` The output of `sim_gs_n` is a data frame with one row per simulation per analysis. -We show results for the first 2 simulated trials here. +We show results for the first 2 simulated trials here. The estimate column is the *sum(0 - E)* for the logrank test; the se column is its standard error estimated under the null hypothesis. -The `z` column is the test statistic for the logrank test (estimate / se). +The `z` column is the test statistic for the logrank test (estimate / se). The `info` and `info0` columns are the information at the current analysis under the alternate and null hypotheses, respectively. ```{r} @@ -181,7 +181,7 @@ sim_res |> ungroup() |> mutate(`Asymptotic power` = x$bound$probability[x$bound$bound == "upper"]) |> lt() |> - lt_header("Summary of 100 simulations") |> + lt_header("Summary of 100 simulations") |> lt_format(columns = 2, decimals = 1) |> lt_format(columns = 3:5, decimals = 2) ```