R-code & some thoughts [Two-Stage / GS Designs]

posted by Helmut Homepage – Vienna, Austria, 2014-12-26 18:51 (3831 d 05:52 ago) – Posting: # 14179
Views: 7,749

Hi Emrah,

❝ Herr Schütz;


First: You replied to ElMaestro and second: I’m fine to be called with my prename Helmut. ;-)

❝ Could you advice a reliable formula to check my calculations ?


Software for Power/sample size: Get R and the package PowerTOST.
I guess you used a ratio of 1 (should be 0.95 for Potvin’s & Montague’s methods) and the shifted (central) t-distribution. I got almost your results:

library(PowerTOST)
n <- 24
cat(sprintf("%.2f%%", 100*power.TOST(CV=CI2CV(lower=0.7781, upper=0.9671, n=n),
  theta0=1, n=n, method="shifted")), "\n")
91.56%
cat(sprintf("%.2f%%", 100*power.TOST(CV=CI2CV(lower=0.7724, upper=1.0097, n=n),
  theta0=1, n=n, method="shifted")), "\n")
73.48%

It’s better to use the exact method or at least the approximation by the noncentral t-dis­tri­bu­tion.

❝ ❝ I assume you wrote in your protocol that your way through the decision tree would be dictated by Cmax and not AUCt? You'll be going into stage 2 before declaring success or failure.


❝ No it will be dictated by both Cmax and AUCt. Assuming that both endpoints are outside the 90% CI and power is below 80% for only one endpoint ? What would be the next step ?


This is what I write in my protocols as well. The procedure for your study (note that you should not necessarily calculate the 90% CIs), Method C: I generally start with Cmax, which likely is higher variable:R-code:

#####################################
# Interim analysis, Potvin Method C #
#####################################
library(PowerTOST)
PK   <- c("Cmax", "AUCt")
n1   <- c(24, 24)
PE   <- c(0.883115, 0.867468)
CV   <- c(0.275241, 0.221999)
TR   <- 0.95
al   <- c(0.05, 0.0294)
CIad <- sprintf("%.2f%%", 100*(1-(2*al[2])))
fail <- 0
n2   <- vector()
for(j in seq_along(PK)) {
  Pw <- power.TOST(alpha=al[1], CV=CV[j], theta0=TR, n=n1[j])
  cat("\nInterim analysis of", PK[j], "\n————————————————————————",
      "\nPower:", paste0(round(100*Pw, 2), "%\n"))
  if(Pw >= 0.8) {
    CI <- CI.BE(alpha=al[1], pe=PE[j], CV=CV[j], n=n1[j])
    if(CI["lower"] < 0.8 | CI["upper"] > 1.25) {
      cat("First stage 90% CI (unadjusted, since power \u226580%):",
        sprintf("%.2f \u2013 %.2f%%", 100*CI[1], 100*CI[2]),
        "\nFailed BE; stop the study.\n")
      fail <- fail + 1
    } else {
    cat("First stage 90% CI (unadjusted, since power \u226580%):",
        sprintf("%.2f \u2013 %.2f%%", 100*CI[1], 100*CI[2]),
        "\nPassed BE; stop the study.\n")
    }
  } else {
    CI <- CI.BE(alpha=al[2], pe=PE[j], CV=CV[j], n=n1[j])
    if(CI["lower"] < 0.8 | CI["upper"] > 1.25) {
      cat("First stage", CIad, "CI (adjusted, since power <80%):",
          sprintf("%.2f \u2013 %.2f%%", 100*CI[1], 100*CI[2]),
          "\nFailed BE; initiate the second stage.\n")
      n <- sampleN.TOST(alpha=al[2], CV=CV[j], theta0=TR,
                        print=FALSE)["Sample size"]
      n2[j] <- as.numeric(n-n1[j])
      cat("Second stage sample size:", n2[j], "subjects.\n")
    } else {
      cat("First stage", CIad, ", CI (power <80%):\n",
          sprintf("%.2f \u2013 %.2f%%", 100*CI[1], 100*CI[2]),
          "\nPassed BE; stop the study.\n")
    }
  }
  if(j == length(PK)) {
    if(fail == 0) {
      cat("\nInitiate the second stage with", max(n2), "subjects.\n\n")
    } else {
      cat("\nSince", fail,
          "PK metric(s) failed in the first stage with \u226580% power,",
          "stop the study.\n")
    }
  }
}


Gives:

Interim analysis of Cmax
————————————————————————
Power: 64.87%
First stage 94.12% CI (adjusted, since power <80%): 75.60 – 103.17%
Failed BE; initiate the second stage.
Second stage sample size: 16 subjects.

Interim analysis of AUCt
————————————————————————
Power: 83.22%
First stage 90% CI (unadjusted, since power ≥80%): 77.81 – 96.71%
Failed BE; stop the study.

Since 1 PK metric(s) failed in the first stage with ≥80% power, stop the study.


I think it is worthwhile to look at the PEs, which were <90%. Did you have some clues which let you assuming them to be 95%? If yes, OK. Shit happens. A conventional fixed-sample design – in up to 60 (!) subjects – would have failed as well.
Let’s play the devil’s advocate: You had some hints that the T/R will be 90%. Then you should better have used Montague’s Method D (α 0.0280) – instead of being overly optimistic:Whether it makes sense to run a study in 82 subjects is yet another story… If you decide to repeat the study (since you failed according to the protocol) I would try to tweak the test formulation or find a closer reference.

No Two-Stage Method is published yet which would allow to stop a study if the PE is outside an acceptable range. Charles Bon suggested at the AAPS Annual Meeting 2007 a futility criterion of <85.00 and >117.65%. Before you apply such a method, you would have to find and validate a suitable αadj. Since your PEs were pretty low there would be some chances that the study stops in the first stage (contrary to Method D which would lead to high sample sizes). Try the function power.2stage.fC() in the package Power2Stage.

Dif-tor heh smusma 🖖🏼 Довге життя Україна! [image]
Helmut Schütz
[image]

The quality of responses received is directly proportional to the quality of the question asked. 🚮
Science Quotes

Complete thread:

UA Flag
Activity
 Admin contact
23,424 posts in 4,927 threads, 1,674 registered users;
18 visitors (0 registered, 18 guests [including 14 identified bots]).
Forum time: 01:44 CEST (Europe/Vienna)

Medical researches can be divided into two sorts:
those who think that meta is better and those
who believe that pooling is fooling.    Stephen Senn

The Bioequivalence and Bioavailability Forum is hosted by
BEBAC Ing. Helmut Schütz
HTML5