|
1 | 1 | test_that("Testing weights calculation", { |
2 | 2 |
|
3 | | - # The following function is almost the same as gs_info_rd. |
4 | | - # The only difference is that: |
5 | | - # gs_info_rd returns `ans` |
6 | | - # gs_info_rd_ returns `tbl` with out removing columns |
7 | | - # If there is a suggested way to avoid copy-pasting these similar functions, please let me know! |
8 | | - gs_info_rd_ <- function(p_c = tibble::tibble(stratum = "All", rate = .2), |
9 | | - p_e = tibble::tibble(stratum = "All", rate = .15), |
10 | | - n = tibble::tibble(stratum = "All", n = c(100, 200, 300), analysis = 1:3), |
11 | | - rd0 = 0, ratio = 1, weight = c("unstratified", "ss", "invar", "mr")) { |
12 | | - |
13 | | - n_analysis <- max(n$analysis) |
14 | | - weight <- match.arg(weight) |
15 | | - |
16 | | - # Pool the input arguments together ---- |
17 | | - suppressMessages( |
18 | | - tbl <- n |> |
19 | | - left_join(p_c) |> |
20 | | - rename(p_c = rate) |> |
21 | | - left_join(p_e) |> |
22 | | - rename(p_e = rate) |> |
23 | | - left_join(if ("data.frame" %in% class(rd0)) { |
24 | | - rd0 |
25 | | - } else { |
26 | | - tibble(analysis = 1:n_analysis, rd0 = rd0) |
27 | | - }) |> |
28 | | - mutate( |
29 | | - n_e = n / (1 + ratio), |
30 | | - n_c = n * ratio / (1 + ratio), |
31 | | - d = ifelse(p_c > p_e, 1, -1), |
32 | | - p_pool_per_k_per_s = (n_c * p_c + n_e * p_e) / n, |
33 | | - p_e0 = (p_c + ratio * p_e - d * rd0) / (ratio + 1), |
34 | | - p_c0 = p_e0 + d * rd0 |
35 | | - ) |
36 | | - ) |
37 | | - |
38 | | - # Calculate the variance of the risk difference ---- |
39 | | - if (is.numeric(rd0) && rd0 == 0) { |
40 | | - tbl <- tbl |> mutate( |
41 | | - sigma2_H0_per_k_per_s = p_pool_per_k_per_s * (1 - p_pool_per_k_per_s) * (1 / n_c + 1 / n_e), |
42 | | - sigma2_H1_per_k_per_s = p_c * (1 - p_c) / n_c + p_e * (1 - p_e) / n_e |
43 | | - ) |
44 | | - } else if ("data.frame" %in% class(rd0) || rd0 != 0) { |
45 | | - tbl <- tbl |> mutate( |
46 | | - sigma2_H0_per_k_per_s = p_c0 * (1 - p_c0) / n_c + p_e0 * (1 - p_e0) / n_e, |
47 | | - sigma2_H1_per_k_per_s = p_c * (1 - p_c) / n_c + p_e * (1 - p_e) / n_e |
48 | | - ) |
49 | | - } |
50 | | - |
51 | | - # Assign weights ---- |
52 | | - if (weight == "unstratified") { |
53 | | - tbl <- tbl |> mutate(weight_per_k_per_s = 1) |
54 | | - } else if (weight == "ss") { |
55 | | - suppressMessages( |
56 | | - tbl <- tbl |> |
57 | | - left_join( |
58 | | - tbl |> |
59 | | - group_by(analysis) |> |
60 | | - summarize(sum_ss = sum(n_c * n_e / (n_c + n_e))) |
61 | | - ) |> |
62 | | - mutate(weight_per_k_per_s = n_c * n_e / (n_c + n_e) / sum_ss) |> |
63 | | - select(-sum_ss) |
64 | | - ) |
65 | | - } else if (weight == "invar") { |
66 | | - suppressMessages( |
67 | | - tbl <- tbl |> |
68 | | - left_join( |
69 | | - tbl |> |
70 | | - group_by(analysis) |> |
71 | | - summarize(sum_inv_var_per_s = sum(1 / sigma2_H1_per_k_per_s)) |
72 | | - ) |> |
73 | | - mutate(weight_per_k_per_s = 1 / sigma2_H1_per_k_per_s / sum_inv_var_per_s) |> |
74 | | - select(-sum_inv_var_per_s) |
75 | | - ) |
76 | | - } else if (weight == "mr") { |
77 | | - suppressMessages( |
78 | | - tbl <- tbl |> |
79 | | - left_join( |
80 | | - tbl |> |
81 | | - group_by(analysis) |> |
82 | | - summarize(sum_inv_var_per_s = sum(1 / sigma2_H1_per_k_per_s)) |
83 | | - ) |> |
84 | | - ungroup() |> |
85 | | - group_by(analysis) |> |
86 | | - mutate(alpha_per_k_per_s = (p_e - p_c) * sum_inv_var_per_s - sum((p_e - p_c) / sigma2_H1_per_k_per_s), |
87 | | - beta_per_k_per_s = 1/sigma2_H1_per_k_per_s * (1 + alpha_per_k_per_s * sum((p_e - p_c) * n / sum(n))), |
88 | | - weight_per_k_per_s = beta_per_k_per_s / sum_inv_var_per_s - |
89 | | - (alpha_per_k_per_s / sigma2_H1_per_k_per_s / (sum_inv_var_per_s + sum(alpha_per_k_per_s * (p_e - p_c) / sigma2_H1_per_k_per_s))) * |
90 | | - (sum((p_e - p_c) * beta_per_k_per_s) / sum_inv_var_per_s) |
91 | | - ) # |> |
92 | | - # select(-c(sum_inv_var_per_s, alpha_per_k_per_s, beta_per_k_per_s)) |
93 | | - ) |
94 | | - } |
95 | | - |
96 | | - return(tbl) |
97 | | - } |
98 | | - |
99 | 3 | # This example following the second example in the paper "Minimum risk weights for comparing treatments in stratified binomial trials" |
100 | 4 | p_c <- data.frame(stratum = c("Stratum1", "Stratum2"), rate = c(0.48, 0.8)) |
101 | 5 | p_e <- data.frame(stratum = c("Stratum1", "Stratum2"), rate = c(0.53, 0.95)) |
102 | 6 | n <- data.frame(stratum = c("Stratum1", "Stratum2"), n = c(63, 37), analysis = 1) |
103 | 7 |
|
104 | | - # Testing the INVAR weight |
105 | | - weight_invar <- gs_info_rd_(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "invar")$weight_per_k_per_s |
106 | | - expect_equal(weight_invar, c(0.41, 0.59), tolerance = 1e-2) |
| 8 | + # sample size |
| 9 | + n_c_stratum1 <- n$n[1] / 2 |
| 10 | + n_e_stratum1 <- n$n[1] / 2 |
| 11 | + n_c_stratum2 <- n$n[2] / 2 |
| 12 | + n_e_stratum2 <- n$n[2] / 2 |
| 13 | + n_stratum1 <- n_c_stratum1 + n_e_stratum1 |
| 14 | + n_stratum2 <- n_c_stratum2 + n_e_stratum2 |
| 15 | + |
| 16 | + # failure rate |
| 17 | + p_c_stratum1 <- p_c$rate[1] |
| 18 | + p_e_stratum1 <- p_e$rate[1] |
| 19 | + p_c_stratum2 <- p_c$rate[2] |
| 20 | + p_e_stratum2 <- p_e$rate[2] |
| 21 | + p_pool_stratum1 <- (p_c_stratum1 + p_e_stratum1)/2 |
| 22 | + p_pool_stratum2 <- (p_c_stratum2 + p_e_stratum2)/2 |
| 23 | + |
| 24 | + # variance for each stratum under H1 |
| 25 | + var_H1_stratum1 <- p_c_stratum1 * (1 - p_c_stratum1) / n_c_stratum1 + p_e_stratum1 * (1 - p_e_stratum1) / n_e_stratum1 |
| 26 | + var_H1_stratum2 <- p_c_stratum2 * (1 - p_c_stratum2) / n_c_stratum2 + p_e_stratum2 * (1 - p_e_stratum2) / n_e_stratum2 |
| 27 | + |
| 28 | + # variance for each stratum under H0 |
| 29 | + var_H0_stratum1 <- p_pool_stratum1 * (1 - p_pool_stratum1) * (1/n_c_stratum1 + 1/n_e_stratum1) |
| 30 | + var_H0_stratum2 <- p_pool_stratum2 * (1 - p_pool_stratum2) * (1/n_c_stratum2 + 1/n_e_stratum2) |
| 31 | + |
| 32 | + # Testing the INVAR weight via the aggregated info0, info1 |
| 33 | + # the weight 0.41 and 0.59 comes from Table IV of "Minimum risk weights for comparing treatments in stratified binomial trials" |
| 34 | + x <- gs_info_rd(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "invar") |
| 35 | + |
| 36 | + expect_equal(1/x$info0, |
| 37 | + 0.41^2 * p_pool_stratum1 * (1 - p_pool_stratum1) * (1 / n_c_stratum1 + 1 / n_e_stratum1) + |
| 38 | + 0.59^2 * p_pool_stratum2 * (1 - p_pool_stratum2) * (1 / n_c_stratum2 + 1 / n_e_stratum2), |
| 39 | + tolerance = 1e-4) |
107 | 40 |
|
108 | | - # Testing the SS weight |
109 | | - weight_ss <- gs_info_rd_(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "ss")$weight_per_k_per_s |
110 | | - expect_equal(weight_ss, c(0.63, 0.37), tolerance = 1e-2) |
| 41 | + expect_equal(1/x$info1, |
| 42 | + 0.41^2 * p_c_stratum1 * (1 - p_c_stratum1) / n_c_stratum1 + 0.41^2 * p_e_stratum1 * (1 - p_e_stratum1) / n_e_stratum1 + |
| 43 | + 0.59^2 * p_c_stratum2 * (1 - p_c_stratum2) / n_c_stratum2 + 0.59^2 * p_e_stratum2 * (1 - p_e_stratum2) / n_e_stratum2, |
| 44 | + tolerance = 1e-4) |
| 45 | + |
| 46 | + # Testing the SS weight via the aggregated info0, info1 |
| 47 | + # the weight 0.63 and 0.37 comes from Table IV of "Minimum risk weights for comparing treatments in stratified binomial trials" |
| 48 | + x <- gs_info_rd(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "ss") |
| 49 | + |
| 50 | + expect_equal(1/x$info0, |
| 51 | + 0.63^2 * p_pool_stratum1 * (1 - p_pool_stratum1) * (1 / n_c_stratum1 + 1 / n_e_stratum1) + |
| 52 | + 0.37^2 * p_pool_stratum2 * (1 - p_pool_stratum2) * (1 / n_c_stratum2 + 1 / n_e_stratum2), |
| 53 | + tolerance = 1e-4) |
| 54 | + |
| 55 | + expect_equal(1/x$info1, |
| 56 | + 0.63^2 * p_c_stratum1 * (1 - p_c_stratum1) / n_c_stratum1 + 0.63^2 * p_e_stratum1 * (1 - p_e_stratum1) / n_e_stratum1 + |
| 57 | + 0.37^2 * p_c_stratum2 * (1 - p_c_stratum2) / n_c_stratum2 + 0.37^2 * p_e_stratum2 * (1 - p_e_stratum2) / n_e_stratum2, |
| 58 | + tolerance = 1e-4) |
111 | 59 |
|
112 | 60 | # Testing the MR weight following formula (10) |
113 | | - x_mr <- gs_info_rd_(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "mr") |
114 | | - V1 <- x_mr$sigma2_H1_per_k_per_s[1] |
115 | | - V2 <- x_mr$sigma2_H1_per_k_per_s[2] |
116 | | - delta1 <- x_mr$p_e[1] - x_mr$p_c[1] |
117 | | - delta2 <- x_mr$p_e[2] - x_mr$p_c[2] |
118 | | - f1 <- x_mr$n[1] / sum(x_mr$n) |
119 | | - f2 <- x_mr$n[2] / sum(x_mr$n) |
| 61 | + # the weight 0.47 and 0.53 comes from Table IV of "Minimum risk weights for comparing treatments in stratified binomial trials" |
| 62 | + x_mr <- gs_info_rd(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "mr") |
| 63 | + V1 <- var_H1_stratum1 |
| 64 | + V2 <- var_H1_stratum2 |
| 65 | + delta1 <- p_e_stratum1 - p_c_stratum1 |
| 66 | + delta2 <- p_e_stratum2 - p_c_stratum2 |
| 67 | + f1 <- n_stratum1 / (n_stratum1 + n_stratum2) |
| 68 | + f2 <- n_stratum2 / (n_stratum1 + n_stratum2) |
120 | 69 |
|
121 | 70 | w1 <- (V2+(delta1-delta2)^2*f1) / (V1 + V2 + (delta1 - delta2)^2) |
122 | 71 | w2 <- 1 - w1 |
123 | | - expect_equal(gs_info_rd_(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "mr")$weight_per_k_per_s, |
124 | | - c(w1, w2)) |
125 | | - |
126 | | - # Note that if is risk difference is constant across strata,then alpha_per_k_per_s is zero |
127 | | - expect_equal(gs_info_rd_(p_c = data.frame(stratum = c("Stratum1", "Stratum2"), rate = c(0.4, 0.8)), |
128 | | - p_e = data.frame(stratum = c("Stratum1", "Stratum2"), rate = c(0.5, 0.9)), |
129 | | - n = data.frame(stratum = c("Stratum1", "Stratum2"), n = c(50, 50), analysis = 1), |
130 | | - rd0 = 0, ratio = 1, weight = "mr")$alpha_per_k_per_s, |
131 | | - c(0, 0)) |
| 72 | + expect_equal(c(w1, w2), c(0.47, 0.53), tolerance = 5e-3) |
| 73 | + |
| 74 | + x <- gs_info_rd(p_c = p_c, p_e = p_e, n = n, rd0 = 0, ratio = 1, weight = "mr") |
| 75 | + |
| 76 | + expect_equal(1/x$info0, |
| 77 | + w1^2 * p_pool_stratum1 * (1 - p_pool_stratum1) * (1 / n_c_stratum1 + 1 / n_e_stratum1) + |
| 78 | + w2^2 * p_pool_stratum2 * (1 - p_pool_stratum2) * (1 / n_c_stratum2 + 1 / n_e_stratum2), |
| 79 | + tolerance = 1e-4) |
| 80 | + |
| 81 | + expect_equal(1/x$info1, |
| 82 | + w1^2 * p_c_stratum1 * (1 - p_c_stratum1) / n_c_stratum1 + w1^2 * p_e_stratum1 * (1 - p_e_stratum1) / n_e_stratum1 + |
| 83 | + w2^2 * p_c_stratum2 * (1 - p_c_stratum2) / n_c_stratum2 + w2^2 * p_e_stratum2 * (1 - p_e_stratum2) / n_e_stratum2, |
| 84 | + tolerance = 1e-4) |
132 | 85 |
|
133 | 86 |
|
134 | 87 | }) |
|
0 commit comments