Bioequivalence and Bioavailability Forum

Main page Policy/Terms of Use Abbreviations Latest Posts

 Log-in |  Register |  Search

Back to the forum  Query: 2017-12-13 08:21 CET (UTC+1h)
 
BE-proff
Senior

Russia,
2017-07-20 14:09

Posting: # 17577
Views: 1,322
 

 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: 1,152
 

 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

A potentially biased estimator may be a relevant estimator. The case of REML speaks volumes.
BE-proff
Senior

Russia,
2017-07-20 15:02

@ ElMaestro
Posting: # 17579
Views: 1,142
 

 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: 1,137
 

 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]Regards,
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: 1,134
 

 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: 1,129
 

 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]Regards,
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: 972
 

 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: 931
 

 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]Regards,
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,556 Posts in 3,758 Threads, 1,091 registered users;
31 users online (0 registered, 31 guests).

The purpose of models is not to fit the data,
but to sharpen the questions.    Samuel Karlin

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