Skip to content

Commit a12f99e

Browse files
committed
Add developer tests to gs_info_rd
1 parent 17da463 commit a12f99e

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
test_that("Testing weights calculation", {
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+
# This example following the second example in the paper "Minimum risk weights for comparing treatments in stratified binomial trials"
100+
p_c <- data.frame(stratum = c("Stratum1", "Stratum2"), rate = c(0.48, 0.8))
101+
p_e <- data.frame(stratum = c("Stratum1", "Stratum2"), rate = c(0.53, 0.95))
102+
n <- data.frame(stratum = c("Stratum1", "Stratum2"), n = c(63, 37), analysis = 1)
103+
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)
107+
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)
111+
112+
# 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)
120+
121+
w1 <- (V2+(delta1-delta2)^2*f1) / (V1 + V2 + (delta1 - delta2)^2)
122+
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))
132+
133+
134+
})
135+

0 commit comments

Comments
 (0)