Define a list of laws (i.e., distributions) with mean and sd.

# functions 
n <- 40 # per group
laws <- list(
  norm = function(mean=0, sd=1) mean + sd *  rnorm(n, 0, 1),
  logn = function(mean=0, sd=1) mean + sd * (rlnorm(n, sdlog=1) - 1.65) / 1.95,
  exp1 = function(mean=0, sd=1) mean + sd * (rexp(n) - 1),
  exp2 = function(mean=0, sd=1) mean + sd * (rexp(n)^2 - 2) / 3.94,
  emix = function(mean=0, sd=1) mean + sd * (c(rep(0, n/2), rexp(n/2)) - 0.5) / 0.84
)
set.seed(123)
options(digits=3)

get_data_all_laws <- function(){
  dat <- lapply(names(laws), function(fname){
    f <- laws[[fname]]
    data.frame(y=f(), fun=fname)
  }) 
  dat <- do.call(rbind, dat)
  dat
}
boxplot(y ~ fun, get_data_all_laws(), main= "Laws illustrated")

Verify mean and standard deviation

sapply(laws, function(f) mean(replicate(10000, mean(f(0, 1)))))
     norm      logn      exp1      exp2      emix 
 1.55e-03 -2.89e-03 -1.66e-03 -8.53e-05 -1.32e-03 
sapply(laws, function(f) mean(replicate(10000, mean(f(1, 2)))))
 norm  logn  exp1  exp2  emix 
1.003 1.002 0.998 0.994 0.997 
sapply(laws, function(f) mean(replicate(10000,   sd(f(0, 1)))))
 norm  logn  exp1  exp2  emix 
0.994 1.008 0.977 0.999 1.000 
sapply(laws, function(f) mean(replicate(10000,   sd(f(1, 2)))))
norm logn exp1 exp2 emix 
1.99 2.01 1.96 1.99 2.00 

Define the tests used

pval_t <- function(d) t.test(y ~ group,d)$p.value
pval_w <- function(d) coin::pvalue(coin::wilcox_test(y ~ group, d))
pval_m <- function(d) coin::pvalue(coin::median_test(y ~ group, d))
# retuns data with f1() for group "A" and f2(mean2, sd2) for group "B"
get_data <- function(f1, f2, mean2=0, sd2=1){
  d <- rbind(
    data.frame(
      y=f1(),
      group="A"
    ),
    data.frame(
      y=f2(mean2, sd2),
      group="B"
    ))
  d$group <- as.factor(d$group)
  d
}

# get power of tests
get_power <- function(f1, f2, nsim=1000, mean2=0, sd2=1) {
  data_list <- replicate(nsim, get_data(f1, f2, mean2=mean2, sd2=sd2), simplify = FALSE)
  c(t = mean(sapply(data_list, pval_t) < 0.05),
    w = mean(sapply(data_list, pval_w) < 0.05),
    m = mean(sapply(data_list, pval_m) < 0.05))
}

# get all combinations of functions
fun_comb <- expand.grid(names(laws), names(laws)) |> as.matrix()
rnames <- apply(fun_comb, 1, paste0, collapse="_")

sim <- function(nsim=1000, mean2=0, sd2=1) {
  fun_comb_list <- split(fun_comb, row(fun_comb))
  coverage <- parallel::mclapply(fun_comb_list, function(f_names){
    f1 <- laws[[f_names[1]]]
    f2 <- laws[[f_names[2]]]
    get_power(f1, f2, nsim=nsim, mean2=mean2, sd2=sd2)
  })
  coverage <- do.call(rbind, coverage) 
  rownames(coverage) <- rnames
  colnames(coverage) <- paste0(
    colnames(coverage), " ", as.character(mean2), " ", as.character(sd2))
  coverage |> as.data.frame()
}

Simulation

nsim <- 500
set.seed(4321)
null <- sim(nsim=nsim)
set.seed(4321)
s_diff <- sim(nsim=nsim, sd2=2)
set.seed(4321)
s_difff <- sim(nsim=nsim, sd2=5)
set.seed(4321)
mu_diff <- sim(nsim=nsim, mean2 = 0.1)
set.seed(4321)
mu_difff <- sim(nsim=nsim, mean2 = 0.2)
results <- cbind(
  null,
  s_diff,
  s_difff,
  mu_diff,
  mu_difff
)
results * 100
  t 0 1 w 0 1 m 0 1 t 0 2 w 0 2 m 0 2 t 0 5 w 0 5 m 0 5 t 0.1 1 w 0.1 1 m 0.1 1 t 0.2 1 w 0.2 1 m 0.2 1
norm_norm 4.2 4.4 3.6 4.4 4.6 5.0 7.0 10.6 10.6 8.4 7.6 4.6 14.4 12.4 8.4
logn_norm 8.0 12.6 33.6 4.2 8.0 16.4 4.8 9.0 14.6 12.8 25.4 45.6 21.0 41.4 59.8
exp1_norm 5.8 9.8 21.4 3.8 5.6 13.6 2.6 6.6 11.6 8.6 17.4 29.4 17.8 32.2 45.8
exp2_norm 5.6 15.4 46.8 5.6 11.4 26.0 3.4 10.6 16.2 11.4 27.2 63.2 21.6 46.4 79.6
emix_norm 3.8 10.2 46.4 5.6 9.6 25.4 4.8 7.8 11.2 10.0 23.8 61.0 15.6 42.4 80.4
norm_logn 5.2 14.2 31.0 7.8 41.0 54.0 7.4 77.0 76.4 4.0 4.8 15.8 12.0 7.8 9.0
logn_logn 5.4 7.8 5.8 7.6 56.8 32.6 10.6 77.6 70.2 6.8 17.4 8.4 14.0 51.4 25.8
exp1_logn 2.8 6.0 4.8 8.4 50.4 28.0 10.8 77.2 64.8 6.2 20.2 7.8 14.4 41.6 18.6
exp2_logn 4.4 7.6 7.8 5.8 58.8 33.8 11.8 80.8 73.2 8.8 9.8 23.4 17.4 52.0 54.0
emix_logn 2.6 4.4 10.0 5.4 55.0 0.8 11.8 76.0 17.0 3.8 35.0 31.0 11.6 92.8 56.6
norm_exp1 3.8 9.4 17.6 6.0 29.6 34.4 8.2 49.6 51.2 5.6 6.2 11.6 10.8 7.2 5.8
logn_exp1 5.0 7.8 5.0 4.8 33.0 17.8 6.8 51.0 44.2 10.8 6.6 9.0 17.8 23.2 18.6
exp1_exp1 4.4 4.6 4.8 5.6 30.0 14.8 7.0 48.4 38.6 7.6 10.2 8.0 12.6 28.2 13.0
exp2_exp1 5.2 11.2 9.2 4.6 33.8 18.6 6.6 49.0 44.4 9.8 6.0 20.2 20.8 21.0 44.6
emix_exp1 2.8 3.8 10.8 4.8 34.2 1.0 6.6 50.4 5.4 4.6 7.0 20.0 12.2 29.2 46.2
norm_exp2 5.2 15.4 48.0 7.8 51.0 80.6 14.6 95.0 94.4 3.6 8.4 29.4 9.2 7.2 17.2
logn_exp2 2.8 9.0 6.8 7.6 86.2 67.8 14.8 97.2 94.6 6.2 38.2 10.6 17.6 69.4 27.4
exp1_exp2 4.4 10.4 7.6 8.6 70.4 57.2 14.2 97.4 93.0 6.2 24.6 7.2 12.8 47.2 16.2
exp2_exp2 4.2 5.6 5.0 9.4 91.0 70.8 11.0 94.8 92.2 5.8 67.8 23.2 12.4 91.0 59.6
emix_exp2 2.0 64.8 9.0 9.0 87.0 7.4 14.4 95.4 48.6 3.6 85.2 35.8 9.8 96.6 61.0
norm_emix 3.2 10.6 47.2 2.4 49.6 77.0 4.0 91.4 90.4 3.6 6.6 32.0 9.6 4.0 18.2
logn_emix 1.8 2.4 9.4 3.6 87.0 61.8 4.0 90.4 86.0 8.2 9.0 2.2 15.4 43.6 0.4
exp1_emix 3.0 5.0 10.8 2.2 85.8 53.4 4.4 92.2 87.4 3.2 14.2 4.2 11.4 35.0 1.0
exp2_emix 1.2 62.0 9.8 2.4 87.0 65.8 4.2 91.2 88.8 5.6 1.0 0.8 18.4 71.6 0.0
emix_emix 1.2 0.0 0.0 2.8 89.2 2.0 3.8 91.6 20.2 2.4 82.4 0.0 10.0 94.8 0.2

Confidence intervals of ratios

prop <- function(ratio, nsim){
  confint_ <- prop.test(round(ratio*nsim), nsim)$conf.int[1:2]
  names(confint_) <- c("lower", "upper")
   c( 
    ratio= ratio,
    confint_
)}
sapply(c(0:4/40, 3:10/20), prop, nsim) |> as.data.frame() * 100
  V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13
ratio 0.00 2.50 5.00 7.5 10.00 15.0 20.0 25.0 30.0 35.0 40.0 45.0 50.0
lower 0.00 1.30 3.33 5.5 7.58 12.0 16.6 21.3 26.1 30.9 35.7 40.6 45.6
upper 0.95 4.27 7.39 10.4 13.05 18.5 23.8 29.1 34.3 39.4 44.5 49.5 54.4

this gives an idea of the uncertainty of a ratio given 500 simulations

redo analysis but with groupwise equal medians

Define a list of laws (i.e., distributions) with median and sd

# functions 
n <- 40 # per group
# mean == to keep notation consistent
laws <- list(
  norm = function(mean=0, sd=1) mean + sd *  rnorm(n, 0, 1)
  ,logn = function(mean=0, sd=1) mean + sd * (rlnorm(n, sdlog=1) - 1.02) / 1.95
  ,exp1 = function(mean=0, sd=1) mean + sd * (rexp(n) - 0.706)
  ,exp2 = function(mean=0, sd=1) mean + sd * (rexp(n)^2 - 0.523) / 3.94
  ,emix = function(mean=0, sd=1) mean + sd * (c(rep(0, n/2), rexp(n/2)) -0.025) / 0.84
)

verify median and standard deviation

sapply(laws, function(f) mean(replicate(10000, median(f(0, 1)))))
     norm      logn      exp1      exp2      emix 
-0.000142 -0.000216  0.002144  0.000204  0.000246 
sapply(laws, function(f) mean(replicate(10000, median(f(1, 2)))))
 norm  logn  exp1  exp2  emix 
1.000 1.001 0.998 1.000 0.999 
sapply(laws, function(f) mean(replicate(10000,     sd(f(0, 1)))))
 norm  logn  exp1  exp2  emix 
0.996 1.006 0.978 1.010 1.003 
sapply(laws, function(f) mean(replicate(10000,     sd(f(1, 2)))))
norm logn exp1 exp2 emix 
1.99 2.00 1.95 1.99 2.01 
boxplot(y ~ fun, get_data_all_laws(), main= "Equal Medians (in expectation)")

set.seed(4321)
null_median <- sim(nsim=nsim)
set.seed(4321)
s_diff_median <- sim(nsim=nsim, sd2=2)
set.seed(4321)
s_difff_median <- sim(nsim=nsim, sd2=5)
set.seed(4321)
mu_diff_median <- sim(nsim=nsim, mean2 = 0.1)
set.seed(4321)
mu_difff_median <- sim(nsim=nsim, mean2 = 0.2)
results_median <- cbind(
  null_median,
  s_diff_median,
  s_difff_median,
  mu_diff_median,
  mu_difff_median
)  
results_median * 100
  t 0 1 w 0 1 m 0 1 t 0 2 w 0 2 m 0 2 t 0 5 w 0 5 m 0 5 t 0.1 1 w 0.1 1 m 0.1 1 t 0.2 1 w 0.2 1 m 0.2 1
norm_norm 4.4 4.0 3.6 4.8 5.6 6.0 3.8 8.4 9.4 7.8 6.6 7.0 14.8 15.2 10.2
logn_norm 22.0 13.0 4.6 13.4 12.6 7.0 7.6 9.8 10.2 13.2 8.0 7.2 6.2 5.8 16.6
exp1_norm 20.8 10.6 3.4 12.6 11.6 6.0 5.4 8.2 9.4 11.8 6.4 6.0 7.8 7.2 12.2
exp2_norm 36.0 23.6 7.6 16.6 16.0 12.0 7.8 15.2 13.0 19.0 11.4 8.8 7.2 5.6 18.6
emix_norm 79.6 58.2 0.8 31.6 29.2 4.2 13.0 18.4 6.4 50.2 29.8 1.4 32.2 17.4 6.2
norm_logn 19.0 11.2 6.6 36.0 12.8 5.2 47.8 9.4 6.8 45.2 32.2 7.0 61.4 48.8 14.6
logn_logn 3.8 5.8 5.4 6.6 7.8 4.0 24.4 11.4 8.6 6.0 15.8 8.8 18.6 54.4 29.4
exp1_logn 3.4 8.6 5.2 9.2 5.6 5.0 23.8 9.2 6.8 6.8 23.6 7.6 13.8 47.4 18.8
exp2_logn 4.6 21.6 6.4 6.2 19.4 8.6 22.4 15.6 12.4 5.2 5.8 14.6 11.8 26.4 38.6
emix_logn 22.2 65.4 0.6 5.2 39.8 1.2 12.8 18.8 3.0 8.6 22.2 0.4 3.8 3.4 8.2
norm_exp1 24.8 13.0 4.2 32.6 9.2 5.4 39.8 7.4 9.0 44.2 25.8 5.8 57.2 43.6 8.8
logn_exp1 3.0 7.4 5.4 8.4 12.8 8.0 23.4 12.6 12.2 8.8 7.6 9.6 16.8 18.4 18.0
exp1_exp1 5.2 5.8 5.8 9.0 8.8 6.8 24.4 9.6 10.8 8.4 10.2 6.8 13.6 26.4 11.8
exp2_exp1 3.8 17.6 6.6 6.8 20.2 10.6 23.4 10.0 11.8 4.4 8.4 9.6 9.2 5.2 19.2
emix_exp1 18.6 53.4 0.6 5.0 32.2 2.2 15.2 15.4 5.0 9.4 28.8 2.2 4.0 11.4 5.2
norm_exp2 34.0 23.6 7.4 59.4 35.4 3.6 73.6 30.0 6.6 54.6 43.8 11.8 72.2 58.0 21.4
logn_exp2 3.4 25.4 6.2 15.4 13.2 3.6 45.2 8.8 8.6 9.8 55.6 18.2 23.0 81.4 47.4
exp1_exp2 6.0 21.8 6.8 13.8 25.0 4.0 45.2 5.8 4.4 8.6 47.4 15.6 23.2 66.6 29.2
exp2_exp2 3.0 5.2 4.4 8.6 17.4 6.8 40.2 14.4 10.8 5.8 62.0 22.2 15.0 92.4 66.4
emix_exp2 17.4 61.0 0.0 3.8 51.6 0.4 21.2 29.2 1.4 5.4 6.8 1.8 1.6 64.2 11.4
norm_emix 75.0 56.6 0.8 97.6 78.6 0.2 100.0 89.6 0.0 89.2 74.2 1.0 97.0 88.8 2.6
logn_emix 23.8 62.8 0.2 65.8 74.6 0.0 98.8 70.4 0.0 32.6 83.8 3.8 58.0 97.0 8.4
exp1_emix 24.4 57.0 0.2 72.2 72.4 0.2 99.4 83.2 0.0 34.0 72.4 1.6 55.8 87.8 4.6
exp2_emix 17.0 64.4 0.2 58.4 66.2 0.0 96.6 0.0 0.0 31.4 93.6 6.2 47.0 99.0 21.4
emix_emix 1.4 0.0 0.0 25.6 6.0 0.0 92.2 0.2 0.0 3.0 85.2 0.0 11.4 94.4 0.4