Formulas… [Study As­sess­ment]

posted by Helmut Homepage – Vienna, Austria, 2025-10-30 11:28 (239 d 02:30 ago) – Posting: # 24473
Views: 3,263

Hi Shuanghe,

diving into the formulas. Ugly as shit in the ICH M9 guideline$$\text{f2}=50\phantom{.}\tiny{\bullet}\normalsize\phantom{.}\log\{\text{[}1+(1/\text{n}){\Sigma_{\text{t=1}}}^\text{n}(\text{R}_\text{t}-\text{T}_\text{t})^2\text{]}^{-0.5}\phantom{.}\tiny{\bullet}\normalsize\phantom{.}100\}\tag{1}$$ which we can beautify to your $$f_2=50\cdot\log_{10}\frac{100}{\sqrt{1+\frac{1}{n}\sum_{t=1}^{t=n}(\text{R}_t-\text{T}_t)^2}}\tag{2}$$ Thanks a lot! I screwed up in my post above because I had overlooked that the exponent of the term in square brackets of \((1)\) is \(0.5\) and not \(0.5\)… If we don’t trust algebra, we can compare the formulas by brute force.

f2 <- function(R, T, formula) {
  if (!length(R) == length(T))
    stop ("R and T vectors must have the same length.")
  if (missing(formula)) formula <- 2 # default
  if (!formula %in% 1:2)
    stop ("formula must be 1 or 2.")
  ms <- mean((R - T)^2) # instead of the clumsy formula
  if (formula == 1) {
    x <- 50 * log10((1 + ms)^-0.5 * 100)
  } else {
    x <- 50 * log10(100 / sqrt(1 + ms))
  }
  return(x)
}

n       <- 20
mu_R    <- mu_T    <- 100
sigma_R <- sigma_T <- 20
# is the package "truncnorm" installed?
inst    <- installed.packages()["truncnorm", "Package"]
if (length(inst) == 1) library(truncnorm)  # if yes, attach it
set.seed(123456)                           # for reproducibility
if (length(inst) == 1) { # truncated normal distribution
  R <- sort(rtruncnorm(n = n, a = 0, b = Inf,
                       mean = mu_R, sd = sigma_R))
  T <- sort(rtruncnorm(n = n, a = 0, b = Inf,
                       mean = mu_T, sd = sigma_T))
} else {                 # workaround to avoid negative values
  R <- sort(abs(rnorm(n = n, mean = mu_R, sd = sigma_R)))
  T <- sort(abs(rnorm(n = n, mean = mu_T, sd = sigma_T)))
}
f2_1 <- f2(R, T, 1)
f2_2 <- f2(R, T, 2)
cat(n, "sorted random values of R and T",
    "\nmean (R) =", sprintf("%8.3f", mean(R)),
    "range:", paste(signif(signif(range(R), 5)), collapse = " – "),
    "\nmean (T) =", sprintf("%8.3f", mean(T)),
    "range:", paste(signif(signif(range(T), 5)), collapse = " – "),
    "\n  f2 (1) =", sprintf("%.4g", f2_1),
    "\n  f2 (2) =", sprintf("%.4g", f2_2),
    "\nAre the results by the two formulas identical?",
    isTRUE(all.equal(f2_1, f2_2)), "\n")

20 sorted random values of R and T
mean (R) =  110.477 range: 77.721 – 150.05
mean (T) =   97.769 range: 45.023 – 131.2
  f2 (1) = 42.37
  f2 (2) = 42.37
Are the results by the two formulas identical? TRUE


Try very different values:

mu_R    <- 100
sigma_R <- 20
mu_T    <- 10
sigma_T <- 2
...
20 sorted random values of R and T
mean (R) =  110.477 range: 77.721 – 150.05
mean (T) =    9.777 range: 4.5023 – 13.12
  f2 (1) = -0.4946
  f2 (2) = -0.4946
Are the results by the two formulas identical? TRUE

Bingo, negative \(\small{f_2}\)!

❝ An example: if the average difference is 100%, then you'll have $$f_2=50\,\log_{10} \frac{100}{\sqrt{1+\frac{1}{n}\sum_{i=1}^{i=n}100^2}} = -0.001.$$

❝ With average difference of 110%, \(f_2=-2.07\).


IMHO, if you have the average difference, you should not square it. You need the average of squared difference. Then:

f2_ms <- function(ms) {
  if (ms < 0) stop ("ms must not be negative.")
  50 * log10(100 / sqrt(1 + ms))
}
ms <- c(0, 99, 100, 110, 99^2, 100^2, 110^2)
for (j in seq_along(ms)) {
  cat(sprintf("Mean sq. diff. = %5.0f, f2 = %+8.3f\n",
              ms[j], f2_ms(ms[j])))
}

Mean sq. diff. =     0, f2 = +100.000
Mean sq. diff. =    99, f2 =  +50.000
Mean sq. diff. =   100, f2 =  +49.892
Mean sq. diff. =   110, f2 =  +48.867
Mean sq. diff. =  9801, f2 =   +0.217
Mean sq. diff. = 10000, f2 =   -0.001
Mean sq. diff. = 12100, f2 =   -2.071


Of course, I can be wrong. Given all that, I think that \(\small{f_2}\) is not useful for comparing (plasma) concentration profiles.

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,655 posts in 4,993 threads, 1,570 registered users;
310 visitors (0 registered, 310 guests [including 25 identified bots]).
Forum time: 14:59 CEST (Europe/Vienna)

Ignorance more frequently begets confidence
than does knowledge.    Charles Darwin

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