BAR

library(BAR)

This vignette provides a step-by-step guidance for applying Bayesian adaptive randomization with binary outcomes using the package BAR.

Function setting

We first specify the unknown true successful probability (e.g., response rate) for each arm. For example, we have three arms with 0.1 for the control arm, 0.5 and 0.8 for two experimental arms, denoted as success_prob = c(.1, .5, .8). We set up a number of burn-ins for each arm before initiating the adaptive randomization procedure. During the burn-in period, an equal randomization for each arm will be employed. Here the number of burn-in is set up to be 10, denoted as n_burn_in = 10, that is, 10 * 3 = 30 patients will be equally randomized to each of three arms. We plan to recruit a total of 150 patients (including number of burn-ins, that is, the BAR procedure for each arm will be applied from the \(31^{st}\) patient) into our study and simulate the trial 100 times, that is, we have tot_num = 150 and reptime = 100. The argument block_size = 1 means that the allocation probability will be updated for the next one incoming patient. An example with block_size \(\neq 1\) is shown later.

get_oc_BAR(success_prob = c(.1, .5, .8), n_burn_in = 10, tot_num = 150, block_size = 1, reptime = 100, seed = 100)
#> $avg_alloc_prob
#> [1] 0.1060667 0.1567333 0.7372000
#> 
#> $avg_pat_num
#> [1]  15.91  23.51 110.58

The above results consist of two parts. The first part $avg_alloc_prob is the average allocation probability for each arm in 100 simulations. The second part $avg_pat_num is the average number of patients assigned to each arm.

Sometimes we may want to see the updated allocation probability path after burn-in for each arm for each simulated trial. We can have these results by setting argument output = "raw" in the get_oc_BAR() function. To save the space of the document, we only show one trial result here. For example, by setting up reptime = 1, we can have the following outputs.

get_oc_BAR(success_prob = c(.1, .5, .8), n_burn_in = 10, tot_num = 150, block_size = 1, reptime = 1, output = "raw", seed = 100)
#> [[1]]
#>        [,1]       [,2]      [,3]
#>   [1,] 0.05 0.29417213 0.6558279
#>   [2,] 0.05 0.29056441 0.6594356
#>   [3,] 0.05 0.28485621 0.6651438
#>   [4,] 0.05 0.26630305 0.6836970
#>   [5,] 0.05 0.30558834 0.6444117
#>   [6,] 0.05 0.27369829 0.6763017
#>   [7,] 0.05 0.24469290 0.7053071
#>   [8,] 0.05 0.23373574 0.7162643
#>   [9,] 0.05 0.21302695 0.7369730
#>  [10,] 0.05 0.21755533 0.7324447
#>  [11,] 0.05 0.22480667 0.7251933
#>  [12,] 0.05 0.19615533 0.7538447
#>  [13,] 0.05 0.05000000 0.9000000
#>  [14,] 0.05 0.15050135 0.7994987
#>  [15,] 0.05 0.13313294 0.8168671
#>  [16,] 0.05 0.16191887 0.7880811
#>  [17,] 0.05 0.15984912 0.7901509
#>  [18,] 0.05 0.05000000 0.9000000
#>  [19,] 0.05 0.05000000 0.9000000
#>  [20,] 0.05 0.17855715 0.7714428
#>  [21,] 0.05 0.14742097 0.8025790
#>  [22,] 0.05 0.05000000 0.9000000
#>  [23,] 0.05 0.23566767 0.7143323
#>  [24,] 0.05 0.25148596 0.6985140
#>  [25,] 0.05 0.24505301 0.7049470
#>  [26,] 0.05 0.17824156 0.7717584
#>  [27,] 0.05 0.19210757 0.7578924
#>  [28,] 0.05 0.12418633 0.8258137
#>  [29,] 0.05 0.16833557 0.7816644
#>  [30,] 0.05 0.15559842 0.7944016
#>  [31,] 0.05 0.05000000 0.9000000
#>  [32,] 0.05 0.09886214 0.8511379
#>  [33,] 0.05 0.11520287 0.8347971
#>  [34,] 0.05 0.22920321 0.7207968
#>  [35,] 0.05 0.12044338 0.8295566
#>  [36,] 0.05 0.21951184 0.7304882
#>  [37,] 0.05 0.34037572 0.6096243
#>  [38,] 0.05 0.30901511 0.6409849
#>  [39,] 0.05 0.28693030 0.6630697
#>  [40,] 0.05 0.25672452 0.6932755
#>  [41,] 0.05 0.39111066 0.5588893
#>  [42,] 0.05 0.20643479 0.7435652
#>  [43,] 0.05 0.16465900 0.7853410
#>  [44,] 0.05 0.11288808 0.8371119
#>  [45,] 0.05 0.11514368 0.8348563
#>  [46,] 0.05 0.19631123 0.7536888
#>  [47,] 0.05 0.20815433 0.7418457
#>  [48,] 0.05 0.26395389 0.6860461
#>  [49,] 0.05 0.32108515 0.6289148
#>  [50,] 0.05 0.32716271 0.6228373
#>  [51,] 0.05 0.12729543 0.8227046
#>  [52,] 0.05 0.16071426 0.7892857
#>  [53,] 0.05 0.15735178 0.7926482
#>  [54,] 0.05 0.22222377 0.7277762
#>  [55,] 0.05 0.28098729 0.6690127
#>  [56,] 0.05 0.29622333 0.6537767
#>  [57,] 0.05 0.34252493 0.6074751
#>  [58,] 0.05 0.26292549 0.6870745
#>  [59,] 0.05 0.27691776 0.6730822
#>  [60,] 0.05 0.05000000 0.9000000
#>  [61,] 0.05 0.12695392 0.8230461
#>  [62,] 0.05 0.14538937 0.8046106
#>  [63,] 0.05 0.09816791 0.8518321
#>  [64,] 0.05 0.19808545 0.7519145
#>  [65,] 0.05 0.15853283 0.7914672
#>  [66,] 0.05 0.23361960 0.7163804
#>  [67,] 0.05 0.17458412 0.7754159
#>  [68,] 0.05 0.12871114 0.8212889
#>  [69,] 0.05 0.19082465 0.7591753
#>  [70,] 0.05 0.10311736 0.8468826
#>  [71,] 0.05 0.12380251 0.8261975
#>  [72,] 0.05 0.12105845 0.8289416
#>  [73,] 0.05 0.05000000 0.9000000
#>  [74,] 0.05 0.05000000 0.9000000
#>  [75,] 0.05 0.05000000 0.9000000
#>  [76,] 0.05 0.05000000 0.9000000
#>  [77,] 0.05 0.05000000 0.9000000
#>  [78,] 0.05 0.05000000 0.9000000
#>  [79,] 0.05 0.05000000 0.9000000
#>  [80,] 0.05 0.05000000 0.9000000
#>  [81,] 0.05 0.05000000 0.9000000
#>  [82,] 0.05 0.05000000 0.9000000
#>  [83,] 0.05 0.05000000 0.9000000
#>  [84,] 0.05 0.05000000 0.9000000
#>  [85,] 0.05 0.05000000 0.9000000
#>  [86,] 0.05 0.05000000 0.9000000
#>  [87,] 0.05 0.05000000 0.9000000
#>  [88,] 0.05 0.05000000 0.9000000
#>  [89,] 0.05 0.05000000 0.9000000
#>  [90,] 0.05 0.05000000 0.9000000
#>  [91,] 0.05 0.05000000 0.9000000
#>  [92,] 0.05 0.05000000 0.9000000
#>  [93,] 0.05 0.05000000 0.9000000
#>  [94,] 0.05 0.05000000 0.9000000
#>  [95,] 0.05 0.05000000 0.9000000
#>  [96,] 0.05 0.05000000 0.9000000
#>  [97,] 0.05 0.05000000 0.9000000
#>  [98,] 0.05 0.05000000 0.9000000
#>  [99,] 0.05 0.05000000 0.9000000
#> [100,] 0.05 0.05000000 0.9000000
#> [101,] 0.05 0.05000000 0.9000000
#> [102,] 0.05 0.05000000 0.9000000
#> [103,] 0.05 0.05000000 0.9000000
#> [104,] 0.05 0.05000000 0.9000000
#> [105,] 0.05 0.05000000 0.9000000
#> [106,] 0.05 0.05000000 0.9000000
#> [107,] 0.05 0.05000000 0.9000000
#> [108,] 0.05 0.05000000 0.9000000
#> [109,] 0.05 0.05000000 0.9000000
#> [110,] 0.05 0.05000000 0.9000000
#> [111,] 0.05 0.05000000 0.9000000
#> [112,] 0.05 0.05000000 0.9000000
#> [113,] 0.05 0.05000000 0.9000000
#> [114,] 0.05 0.05000000 0.9000000
#> [115,] 0.05 0.05000000 0.9000000
#> [116,] 0.05 0.05000000 0.9000000
#> [117,] 0.05 0.05000000 0.9000000
#> [118,] 0.05 0.05000000 0.9000000
#> [119,] 0.05 0.05000000 0.9000000
#> [120,] 0.05 0.05000000 0.9000000

From the result above, since 10 * 3 = 30 sample size has been used in the burn-in period, we therefore have 120 (= 150 - 30) patients in the adaptive randomization period. We can see the updated allocation probabilities for each arm in each step after the burn-in period.

In this package, we also provide users flexibility to allow update the allocation probability block-wisely by using the block_size argument. For example, if block_size = 1, it indicates that the assignment of a new patient depends on the previous patients’ responses to treatment in the ongoing trial while block_size = 3, the assignment of next 3 new patients depend on the previous patients’ responses to treatment. An example is shown as below.

get_oc_BAR(success_prob = c(.1, .5, .8), n_burn_in = 10, tot_num = 150, block_size = 3, reptime = 100, seed = 100)
#> $avg_alloc_prob
#> [1] 0.1046667 0.1786667 0.7166667
#> 
#> $avg_pat_num
#> [1]  15.7  26.8 107.5

Bayesian adaptive randomization with fixed allocation ratio for the control arm

In this case, the allocation probability will hold constant for the control arm, which is a usual practice since we want to maintain a good number for the control such that if we want to conduct hypothesis tests between experimental and control arms, we can have a desirable power and results can be interpreted. For this, we can have this argument setting control_arm = "fixed" in the function, which will make the allocation probability of control arm (the first slot) to be fixed to \(\frac{1}{K}\), where K indicates total number of arms (including control arm).

get_oc_BAR(success_prob = c(.1, .5, .8), n_burn_in = 10, tot_num = 150, block_size = 1, reptime = 100, control_arm = "fixed", seed = 100)
#> $avg_alloc_prob
#> [1] 0.3321333 0.1346000 0.5332667
#> 
#> $avg_pat_num
#> [1] 49.82 20.19 79.99

From the result above, we can see the average allocation probability for control arm is close to 0.33 = \(\frac{1}{K},\) where K = 3 here.

Calculate the allocation probability for the next block of new patients using Bayesian adaptive randomization

Here, we provide two examples. The first example uses the power_c to be \(\frac{n}{2N}\) (this is a default option), here, N is the pre-planned total sample size and n is the accumulative sample size when updating the allocation probabilities. In this case, we need to have N, an example is shown below.

next_allocation_rate_BAR(n = c(20, 25, 30), success_count = c(2, 9, 15), tot_num = 150, power_c = "n/2N")
#> [1] 0.0500000 0.2664958 0.6835042

In this example (outputs shown above), we can see that we have 3 arms (the \(1^{st}\) is control and \(2^{rd}\) and \(3^{nd}\) are experimental arms). The study plans to enroll 150 patients and at the time of updating the allocation probabilities for the next patient, the accrual number of patients for the three arms are 20, 25 and 30 with number of responders of 2, 9, and 15, respectively. By using the BAR algorithm, we can compute the allocation probabilities for these three arms are 0.05, 0.266 and 0.684, respectively.

Another example is that we use the power_c to be a numeric, e.g., 0.5. In this case, the N is not required. Even you can see that there is still a N in the below code, this N is no use and plays no role in updating the allocation probabilities. Outputs are shown below and can be interpreted similarly.

next_allocation_rate_BAR(n = c(20, 25, 30), success_count = c(2, 10, 15), tot_num = 150, power_c = .5)
#> [1] 0.0500000 0.1853522 0.7646478