Exact power and sample size, Part III [🇷 for BE/BA]

posted by d_labes  – Berlin, Germany, 2009-11-23 15:50 (5261 d 19:48 ago) – Posting: # 4376
Views: 10,568

Dear All!

Here comes part III of the story. Puzzling all the helpers together we obtain:

# ----- helper functions for sampleN.TOST ---------------------------
# --------------------------------------------------------------------
# Sample size for a desired power, large sample approx.
# bk = design constant, see known.designs()

.sampleN0 <- function(alpha=0.05, targetpower=0.8, theta1, theta2, diffm, se,
                     steps=2, bk=2)
{
    z1 <- qnorm(1-alpha)
    if (abs(diffm)>0.0001) z2 <- qnorm(targetpower)
      else z2 <- qnorm(1-(1-targetpower)/2)
    n01<-(bk/2)*((z1+z2)*(se*sqrt(2)/(diffm-theta1)))^2;
    n02<-(bk/2)*((z1+z2)*(se*sqrt(2)/(diffm-theta2)))^2;
    n0 <- max(n01,n02)
    n0 <- ceiling(n0)
    #make an even multiple of step (=2 in case of 2x2 cross-over)
    n0 <- steps*trunc(n0/steps)
    if (n0<4) n0 <- 4   # minimum sample size
   
    return(n0)
}

# --------------------------------------------------------------------------
# Power of two-one-sided-t-tests using OwensQ or approx. using non-central t
# (this is a wrapper to .power.TOST(...) and .approx.power.TOST(...))
# In case of logscale=TRUE give ldiff, ltheata1 and ltheta2 as ratios
# f.i. ldiff=0.95, ltheta1=0.8, ltheta2=1.25
# In case of logscale=FALSE give ldiff, ltheata1 and ltheta2 as
# difference to 1, f.i. ldiff=0.05 (5% difference) ltheata1=-0.2,
# ltheta2=0.2 (20% equiv. margins)
# CV is always the coefficient of variation but as ratio, not %


power.TOST <- function(alpha=0.05, logscale=TRUE, ltheta1=0.8, ltheta2,
                       ldiff=0.95, CV, n, design="2x2", exact=TRUE)
{
    # design characteristics
    d.no <- .design.no(design)
    if (is.na(d.no)) stop("Err: unknown design!")
   
    dfe <- .design.df(d.no) # degrees of freedom as expression
    bk  <- .design.bk(d.no) # design const.
   
    if (logscale) {
        if (missing(ltheta2)) ltheta2 <- 1/ltheta1
        theta1 <- log(ltheta1)
        theta2 <- log(ltheta2)
        diffm  <- log(ldiff)
        se     <- sqrt(log(1.+CV^2))
    } else {
        if (missing(ltheta2)) ltheta2 <- -ltheta1
        theta1 <- ltheta1
        theta2 <- ltheta2
        diffm  <- ldiff
        se     <- CV
    }
   
    df <- eval(dfe)
    if ( !exact )
      pow <- .approx.power.TOST(alpha, theta1, theta2, diffm, se, n, df, bk)
    else
      pow <- .power.TOST(alpha, theta1, theta2, diffm, se, n, df, bk)
   
    return( pow )

}

Again: Use it on your own risk! The author does not take any responsibility for damage of your computer, your career or of the world :-D .

Regards,

Detlew

Complete thread:

UA Flag
Activity
 Admin contact
22,988 posts in 4,825 threads, 1,657 registered users;
91 visitors (0 registered, 91 guests [including 2 identified bots]).
Forum time: 12:39 CEST (Europe/Vienna)

The whole purpose of education is
to turn mirrors into windows.    Sydney J. Harris

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