Bioequivalence and Bioavailability Forum

Main page Policy/Terms of Use Abbreviations Latest Posts

 Log-in |  Register |  Search

Back to the forum  Query: 2017-08-24 06:58 CEST (UTC+2h)
 
BE-proff
Senior

Russia,
2017-07-20 14:09

Posting: # 17577
Views: 570
 

 How to create table of results [Power / Sample Size]

Hi All,

I need to calculate sample sizes providing CV=0.26 and ratio varying from 0.85 to 1.20 with step 0,05.
How to make a script in R which returns a table with results?:confused:

Thank you


Edit: Category changed. [Helmut]
ElMaestro
Hero

Denmark,
2017-07-20 14:32

@ BE-proff
Posting: # 17578
Views: 499
 

 How to create table of results

Hi BE-proff,

try this:

library(PowerTOST)

arrGMR=c(0.85, 0.9, 0.95, 1.0, 1.05, 1.10, 1.15, 1.20)
myCV=0.26
N=arrGMR

for (i in 1:length(arrGMR))
   N[i]=sampleN.TOST(theta0=arrGMR[i], CV=myCV, targetpower=0.8) [1,7] 

A=data.frame(arrGMR, N)

print(A)


you can easily put it inside a little function if the purpose is specifcally to "return" the data frame (as in, a table).

You can make the code totally fancier and totally unreadable by using sapply or some similar function - I am sure this is what the code police recommends.:-D

I could be wrong, but…


Best regards,
ElMaestro

- since June 2017 having an affair with the bootstrap.
BE-proff
Senior

Russia,
2017-07-20 15:02

@ ElMaestro
Posting: # 17579
Views: 494
 

 How to create table of results

Hi ElMaestro,

Many thanks for the code but I am just user of scripts :-D

So that recommendations like "insert" or "use function" are not for me :-D

But you are right - the purpose is to make a table with results :yes:
Helmut
Hero
Homepage
Vienna, Austria,
2017-07-20 15:18

@ BE-proff
Posting: # 17580
Views: 488
 

 How to create table of sample sizes / powers

Hi BE-proff,

try this (for 80 and 90% target power):

CV     <- 0.26
theta0 <- seq(0.85, 1.20, 0.05)
thetas <- length(theta0)
target <- c(0.8, 0.9)
result <- data.frame(CV=rep(CV, thetas), GMR=sprintf("%.4f", theta0),
                     n1=rep(NA, thetas), pwr1=rep(NA, thetas),
                     n2=rep(NA, thetas), pwr2=rep(NA, thetas))
names(result)[3:6] <- rep(c("n", "power"), 2)
for (j in seq_along(theta0)) {
  x1 <- sampleN.TOST(CV=CV, theta0=theta0[j],
                     targetpower=target[1], print=F)
  x2 <- sampleN.TOST(CV=CV, theta0=theta0[j],
                     targetpower=target[2], print=F)
  result[j, 3] <- x1[["Sample size"]]
  result[j, 4] <- sprintf("%.2f%%", 100*x1[["Achieved power"]])
  result[j, 5] <- x2[["Sample size"]]
  result[j, 6] <- sprintf("%.2f%%", 100*x2[["Achieved power"]])
}
print(result, row.names=FALSE)

Should give:

   CV    GMR   n  power   n  power
 0.26 0.8500 222 80.09% 308 90.15%
 0.26 0.9000  60 80.18%  84 90.57%
 0.26 0.9500  30 80.63%  40 90.31%
 0.26 1.0000  24 80.03%  30 90.12%
 0.26 1.0500  30 81.51%  40 91.01%
 0.26 1.1000  52 80.76%  70 90.02%
 0.26 1.1500 118 80.09% 164 90.23%
 0.26 1.2000 488 80.09% 674 90.01%

Note that power curves are not symmetrical around 100%. If you assume a ∆ of 10% (without knowing whether T will be lower or higher than R), work with 0.90. The sample size will cover 1.10 as well.
Try this:

theta0 <- seq(0.85, 1, 0.05)
theta0 <- unique(c(theta0, rev(1/theta0)))
thetas <- length(theta0)

Should give:

   CV    GMR   n  power   n  power
 0.26 0.8500 222 80.09% 308 90.15%
 0.26 0.9000  60 80.18%  84 90.57%
 0.26 0.9500  30 80.63%  40 90.31%
 0.26 1.0000  24 80.03%  30 90.12%
 0.26 1.0526  30 80.63%  40 90.31%
 0.26 1.1111  60 80.18%  84 90.57%
 0.26 1.1765 222 80.09% 308 90.15%

Do you get the idea?

[image]All the best,
Helmut Schütz 
[image]

The quality of responses received is directly proportional to the quality of the question asked. ☼
Science Quotes
BE-proff
Senior

Russia,
2017-07-20 16:00

@ Helmut
Posting: # 17582
Views: 485
 

 How to create table of sample sizes / powers

Hi Helmut,

No, I didn't catch an idea. :-(
Do you think that absence of symmetry critical?
Helmut
Hero
Homepage
Vienna, Austria,
2017-07-20 17:12

@ BE-proff
Posting: # 17583
Views: 470
 

 Symmetrical in log-scale

Hi BE-proff,

» No, I didn't catch an idea. :-(
» Do you think that absence of symmetry critical?

Power curves are asymmetrical around 1 in linear scale (as is the acceptance range) but symmetrical around 0 in logarithmic scale (AR: ±0.2231). Try this (CV 0.26, GMR 0.9, n 60 for target power 80%):

library(PowerTOST)
CV     <- 0.26
GMR    <- 0.90
theta0 <- seq(1/1.3, 1.3, length.out=501)
n      <- sampleN.TOST(CV=0.26, theta0=GMR, print=FALSE)[["Sample size"]]
power  <- numeric(length(theta0))
for (j in seq_along(theta0)) {
  power[j] <- power.TOST(CV=CV, theta0=theta0[j], n=n)
}
op     <- par(no.readonly=TRUE)
par(pty="s")
# linear scale #
plot(theta0, power, type="l", las=1, col="blue", lwd=2,
     xlim=c(2-max(theta0), max(theta0)), ylim=c(0, 1))
grid()
abline(h=0.05, col="red", lty="dotted")
abline(v=c(1, GMR, 1/GMR), col=c("black", rep("blue", 2)))
mtext(sprintf("%.4f", c(GMR, 1/GMR)), side=3,
      at=c(GMR, 1/GMR), line=1)
# logarithmic scale #
plot(log(theta0), power, type="l", las=1, col="blue", lwd=2,
     xlim=c(-1, +1)*max(abs(range(log(theta0)))), ylim=c(0, 1))
abline(h=0.05, col="red", lty="dotted")
grid()
abline(h=0.05, col="red", lty="dotted")
abline(v=log(c(1, GMR, 1/GMR)), col=c("black", rep("blue", 2)))
mtext(sprintf("%+.4f", log(c(GMR, 1/GMR))), side=3,
      at=log(c(GMR, 1/GMR)), line=1)
par(op)


[image]

The power curve is positively skewed. For any –∆ you get the same power at 1/∆. In the example: For GMR 1.1111 as for GMR 0.90 since 1/0.90 = 1.1111. In many protocols I read “planned for a T/R-ratio of 0.90 to 1.10”. Nope. If the sample size estimation was done for 0.90 it covers anything up to 1.1111. Or the other way ’round: If it was done for 1.10 it would cover anything down to only 1/1.1 = 0.9091 (and not 0.90). Hence, the latter is stupid – unless you know (!) that the GMR will be >1. If you don’t know the sign of ∆, always plan for a GMR <1 and you will be on the safe side.

The second part of the script demonstrates that in log-scale (where the entire analysis is done) everything is symmetrical indeed:

[image]

Hope that helps.

[image]All the best,
Helmut Schütz 
[image]

The quality of responses received is directly proportional to the quality of the question asked. ☼
Science Quotes
BE-proff
Senior

Russia,
2017-07-24 11:42

@ Helmut
Posting: # 17599
Views: 329
 

 Symmetrical in log-scale

Hi Helmut,

Many thanks for clarification! :clap:

Could you please tell how to add study design to :confused:
library(PowerTOST)
CV     <- 0.26
theta0 <- seq(0.85, 1.20, 0.05)
thetas <- length(theta0)
target <- c(0.8, 0.9)
result <- data.frame(CV=rep(CV, thetas), GMR=sprintf("%.4f", theta0),
                     n1=rep(NA, thetas), pwr1=rep(NA, thetas),
                     n2=rep(NA, thetas), pwr2=rep(NA, thetas))
names(result)[3:6] <- rep(c("n", "power"), 2)
for (j in seq_along(theta0)) {
  x1 <- sampleN.TOST(CV=CV, theta0=theta0[j],
                     targetpower=target[1], print=F)
  x2 <- sampleN.TOST(CV=CV, theta0=theta0[j],
                     targetpower=target[2], print=F)
  result[j, 3] <- x1[["Sample size"]]
  result[j, 4] <- sprintf("%.2f%%", 100*x1[["Achieved power"]])
  result[j, 5] <- x2[["Sample size"]]
  result[j, 6] <- sprintf("%.2f%%", 100*x2[["Achieved power"]])
}
print(result, row.names=FALSE)
Helmut
Hero
Homepage
Vienna, Austria,
2017-07-24 18:18

@ BE-proff
Posting: # 17600
Views: 289
 

 RTFM

Hi BE-proff,

no need to copypaste my entire code.

» Could you please tell how to add study design to :confused:

Please do your homework and RTFM:

library(PowerTOST)
help(sampleN.TOST)
help(known.designs)

Online:

sampleN.TOST
known.designs


Add the design-string (as provided in second column of known.designs()) as an argument to sampleN.TOST(...) in the two lines starting with x1 <- and x2 <-
Easy.

[image]All the best,
Helmut Schütz 
[image]

The quality of responses received is directly proportional to the quality of the question asked. ☼
Science Quotes
Back to the forum Activity
 Thread view
Bioequivalence and Bioavailability Forum | Admin contact
17,243 Posts in 3,687 Threads, 1,057 registered users;
25 users online (0 registered, 25 guests).

I try not to think with my gut.
If I’m serious about understanding the world,
thinking with anything besides my brain, as tempting as that might be,
is likely to get me into trouble.    Carl Sagan

The BIOEQUIVALENCE / BIOAVAILABILITY FORUM is hosted by
BEBAC Ing. Helmut Schütz
XHTML/CSS RSS Feed