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

posted by Helmut Homepage – Vienna, Austria, 2014-12-26 18:51 (4186 d 14:22 ago) – Posting: # 14179
Views: 8,889

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,653 posts in 4,991 threads, 1,570 registered users;
106 visitors (0 registered, 106 guests [including 24 identified bots]).
Forum time: 10:14 CEST (Europe/Vienna)

To propose that poor design can be corrected by subtle analysis techniques
is contrary to good scientific thinking.    Stuart J. Pocock

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