Merged block randomization is a restricted randomization method designed for small clinical trials (at most 100 subjects) or trials with small strata, for example in multicentre trials. It can be used for more than two groups (treatment arms) or unequal randomization ratios.
There are two functions in the mergedblocks package:
mergedblocks()
, to create randomization lists for a single stratum.mergedblocksmulti()
, to create randomization lists for multiple strata.The package can be installed by typing install.packages("mergedblocks")
in the R terminal. In addition to the package, a Shiny app is available from https://svdpas.shinyapps.io/mergedblocks/, which can be used to create randomization lists for two groups (treatment arms).
A detailed description of the method is available in Van der Pas (2019). Merged block randomisation: A novel randomisation procedure for small clinical trials. Clinical Trials 16(3):246-252.
In this vignette, we provide a guided tour of the two functions in the package, illustrating the options within each function. The sections are:
mergedblocks()
mergedblocksmulti()
mergedblocks()
For two treatment arms with 1:1 allocation, mergedblocks()
only requires the number of individuals to be randomized as input, via the argument n
. For example, we obtain a randomization list for 50 individuals via:
mergedblocks(n = 50)
#> [1] "1" "1" "2" "1" "2" "2" "2" "1" "2" "1" "2" "1" "1" "1" "2" "2" "2" "1" "2"
#> [20] "1" "1" "2" "1" "1" "2" "2" "1" "1" "2" "2" "2" "1" "1" "2" "2" "2" "1" "2"
#> [39] "1" "2" "1" "1" "2" "1" "2" "1" "2" "1" "1" "2"
By default, the two groups will get numeric labels, in this case “1” and “2”. You can select custom labels with the labels
argument. For example:
mergedblocks(n = 50, labels = c("treatment", "placebo"))
#> [1] "placebo" "treatment" "treatment" "placebo" "placebo" "treatment"
#> [7] "treatment" "treatment" "placebo" "placebo" "placebo" "treatment"
#> [13] "placebo" "treatment" "treatment" "placebo" "treatment" "treatment"
#> [19] "placebo" "treatment" "placebo" "placebo" "placebo" "placebo"
#> [25] "treatment" "treatment" "placebo" "treatment" "placebo" "treatment"
#> [31] "placebo" "treatment" "treatment" "placebo" "treatment" "placebo"
#> [37] "treatment" "placebo" "treatment" "treatment" "placebo" "placebo"
#> [43] "placebo" "treatment" "placebo" "treatment" "treatment" "placebo"
#> [49] "placebo" "placebo"
The argument ratio
can be used to select the desired randomization ratio. For example, if we wish to randomize 50 individuals to two groups in a 1:2 ratio, with allocations labelled as “A” and “B”, we would use:
mergedblocks(n = 50, ratio = c(1, 2), labels = c("A", "B"))
#> [1] "B" "A" "A" "B" "A" "B" "B" "B" "B" "B" "A" "B" "B" "B" "A" "B" "B" "A" "A"
#> [20] "B" "B" "A" "B" "B" "B" "B" "A" "B" "A" "B" "B" "B" "B" "A" "A" "B" "B" "B"
#> [39] "A" "B" "A" "B" "B" "A" "B" "B" "A" "B" "B" "A"
Or for a 3:2 ratio:
The argument ratio
can be used to obtain randomization lists for more than two treatment arms. Suppose the number of treatment arms is \(N\). Then the ratio
argument is set to a vector of length \(N\), with the entries of the vector indicating the desired randomization ratio.
For example, to randomize 50 subjects to three treatment arms in a 1:1:1 ratio:
mergedblocks(n = 50, ratio = c(1, 1, 1))
#> [1] "1" "2" "2" "3" "3" "1" "3" "3" "2" "1" "2" "1" "2" "3" "1" "1" "3" "2" "2"
#> [20] "1" "2" "1" "3" "3" "1" "1" "3" "2" "2" "3" "2" "1" "3" "1" "2" "3" "1" "1"
#> [39] "3" "2" "2" "1" "3" "2" "3" "1" "3" "3" "2" "2"
If other labels than the default numeric ones are desired, the argument labels
can be used. It requires a vector of the same length as ratio
. For example, 1:1:1 allocation to treatments “A”, “B” and “C”:
mergedblocks(n = 50, ratio = c(1, 1, 1), labels = c("A", "B", "C"))
#> [1] "A" "B" "C" "C" "B" "A" "C" "A" "B" "B" "B" "C" "A" "C" "A" "C" "A" "A" "B"
#> [20] "B" "C" "C" "A" "C" "A" "B" "A" "B" "C" "B" "A" "C" "B" "A" "A" "B" "C" "B"
#> [39] "A" "C" "B" "B" "C" "C" "C" "B" "A" "A" "A" "C"
For e.g. five treatment arms:
mergedblocks(n = 50, ratio = c(1, 1, 1, 1, 1), labels = c("A", "B", "C", "D", "E"))
#> [1] "B" "A" "E" "C" "A" "D" "C" "C" "D" "B" "E" "B" "A" "E" "A" "D" "B" "D" "C"
#> [20] "E" "E" "D" "E" "C" "A" "B" "E" "A" "A" "C" "C" "D" "D" "B" "B" "C" "B" "E"
#> [39] "A" "D" "E" "E" "D" "A" "A" "B" "C" "A" "E" "B"
Unequal allocation is also possible. For example, to randomize 50 individuals to three treatment arms, “A”, “B” and “C”, in a 1:1:2 ratio:
mergedblocks(n = 50, ratio = c(1, 1, 2), labels = c("A", "B", "C"))
#> [1] "A" "B" "C" "B" "A" "C" "A" "C" "C" "C" "B" "C" "C" "B" "B" "C" "A" "C" "C"
#> [20] "C" "A" "A" "C" "B" "A" "C" "B" "A" "B" "C" "C" "C" "C" "A" "A" "C" "C" "C"
#> [39] "B" "C" "B" "A" "B" "C" "C" "A" "C" "B" "A" "C"
The arguments of ratio
and labels
are linked In the example above, treatment “C” was assigned twice as often as “A” or “B”. With the following code, treatment “A” is assigned twice as often as “B” or “C” (2:1:1 ratio).
mergedblocks(n = 50, ratio = c(2, 1, 1), labels = c("A", "B", "C"))
#> [1] "A" "B" "A" "C" "B" "C" "A" "A" "C" "A" "B" "A" "B" "A" "A" "B" "C" "C" "A"
#> [20] "A" "A" "B" "A" "C" "C" "A" "A" "B" "A" "B" "C" "A" "A" "A" "C" "B" "A" "B"
#> [39] "A" "C" "C" "C" "A" "A" "B" "A" "A" "A" "B" "A"
As a final example, to randomize 100 individuals to four treatment arms in a 2:2:3:3 ratio:
four.arms <- mergedblocks(n = 100, ratio = c(2, 2, 3, 3), labels = c("A", "B", "C", "D"))
four.arms
#> [1] "D" "C" "B" "A" "C" "A" "D" "C" "B" "A" "D" "D" "D" "B" "D" "C" "C" "C"
#> [19] "C" "A" "A" "B" "C" "C" "B" "D" "D" "A" "B" "D" "C" "C" "B" "D" "D" "D"
#> [37] "B" "A" "D" "C" "C" "D" "A" "C" "B" "A" "D" "B" "A" "C" "A" "A" "C" "D"
#> [55] "B" "B" "C" "D" "D" "C" "D" "A" "A" "D" "C" "A" "B" "C" "A" "C" "C" "C"
#> [73] "B" "B" "D" "D" "D" "A" "B" "B" "C" "B" "C" "D" "C" "D" "D" "C" "D" "D"
#> [91] "A" "C" "B" "D" "A" "A" "B" "C" "C" "A"
table(four.arms)
#> four.arms
#> A B C D
#> 21 20 30 29
The randomization lists can be saved using e.g. write.table()
or write.csv()
. For example:
example.list <- mergedblocks(n = 50, ratio = c(1, 2), labels = c("A", "B"))
write.csv2(example.list, file = "./YourFilePath/ExampleList.csv")
This particular example will yield a CSV file with two columns. The first column contains the numbers 1-50, the second column contains the allocations.
mergedblocksmulti()
The function mergedblocksmulti()
can be used to create randomization lists for multiple strata, as in a multicentre trial. The function allows for different sample sizes per stratum, and for unequal randomization ratios.
The function mergedblocksmulti()
has four arguments. The arguments ratio
and labels
work the same as for the single stratum function mergedblocks()
. The focus of this part of the vignette will be on K
and n
, the two arguments that work differently compared to the arguments of mergedblocks()
.
The argument K
is set to the number of strata. If the number of individuals per stratum is the same for each stratum, the argument n
can be set to this number.
For example, to create randomization lists for three strata with 25 individuals per stratum:
mergedblocksmulti(K = 3, n = 25)
#> V1 V2 V3
#> 1 2 1 2
#> 2 1 1 1
#> 3 1 2 1
#> 4 2 2 1
#> 5 1 1 2
#> 6 2 1 2
#> 7 2 2 2
#> 8 1 2 1
#> 9 2 2 1
#> 10 1 1 2
#> 11 1 2 1
#> 12 2 1 2
#> 13 1 1 1
#> 14 2 1 1
#> 15 2 2 2
#> 16 2 2 1
#> 17 1 1 2
#> 18 1 2 2
#> 19 2 2 1
#> 20 2 1 2
#> 21 1 2 2
#> 22 1 1 2
#> 23 1 2 1
#> 24 1 1 1
#> 25 2 2 2
In the code above, default 1:1 allocation was used, with default numeric treatment labels. The output is a dataframe with one column for each stratum. As for mergedblocks()
, the allocation ratio can be changed to e.g. 1:2 allocation, and custom labels can be used, e.g. “treatment” and “placebo”:
mergedblocksmulti(K = 3, n = 25, ratio = c(1, 2), labels = c("treatment", "placebo"))
#> V1 V2 V3
#> 1 placebo treatment placebo
#> 2 placebo placebo treatment
#> 3 treatment treatment placebo
#> 4 placebo placebo placebo
#> 5 placebo placebo placebo
#> 6 treatment placebo placebo
#> 7 treatment treatment placebo
#> 8 placebo placebo treatment
#> 9 placebo treatment treatment
#> 10 treatment placebo treatment
#> 11 placebo placebo placebo
#> 12 placebo placebo placebo
#> 13 placebo placebo placebo
#> 14 treatment treatment placebo
#> 15 placebo treatment placebo
#> 16 treatment placebo placebo
#> 17 placebo placebo treatment
#> 18 treatment placebo treatment
#> 19 placebo placebo placebo
#> 20 placebo treatment treatment
#> 21 placebo treatment placebo
#> 22 placebo placebo placebo
#> 23 treatment placebo treatment
#> 24 treatment placebo placebo
#> 25 placebo treatment placebo
As a further example, the following code yields randomization lists for four strata, 30 individuals per stratum, with 1:1:1 allocation of three treatments labelled “A”, “B” and “C”.
mergedblocksmulti(K = 4, n = 30, ratio = c(1, 1, 1), labels = c("A", "B", "C"))
#> V1 V2 V3 V4
#> 1 A A B C
#> 2 B C C A
#> 3 A B A B
#> 4 C A C B
#> 5 A B B A
#> 6 B C A C
#> 7 C B C A
#> 8 C B B B
#> 9 C A A B
#> 10 B C B C
#> 11 B A C C
#> 12 A B C A
#> 13 B C A A
#> 14 C C A B
#> 15 C C A C
#> 16 B B B B
#> 17 A A B C
#> 18 A A C B
#> 19 A C A C
#> 20 B B C A
#> 21 C B B A
#> 22 A A C C
#> 23 C B A A
#> 24 B C C B
#> 25 A A A A
#> 26 C C B C
#> 27 B A A B
#> 28 B A B B
#> 29 A A B A
#> 30 B C C C
The argument n
can be used to incorporate varying sample sizes. For example, suppose we have three strata, with sample sizes 20, 30 and 25 In each stratum, 1:1 allocation to treatments “A” and “B” is desired. We could use the following code:
mergedblocksmulti(K = 3, n = c(20, 30, 25), ratio = c(1, 1), labels = c("A", "B"))
#> V1 V2 V3
#> 1 A A A
#> 2 B B B
#> 3 B B A
#> 4 A A B
#> 5 B B A
#> 6 A A B
#> 7 B B B
#> 8 A A B
#> 9 B A A
#> 10 A B A
#> 11 B B B
#> 12 A A A
#> 13 B B B
#> 14 A A A
#> 15 A A A
#> 16 A B A
#> 17 B B B
#> 18 B A B
#> 19 A A A
#> 20 A B B
#> 21 <NA> A A
#> 22 <NA> B B
#> 23 <NA> B B
#> 24 <NA> A A
#> 25 <NA> A A
#> 26 <NA> B <NA>
#> 27 <NA> A <NA>
#> 28 <NA> A <NA>
#> 29 <NA> B <NA>
#> 30 <NA> A <NA>
The argument n
is now set to a vector with the desired sample sizes. The output is a dataframe with three columns, one per stratum. The columns with sample sizes 20 and 25 are padded with NAs.
As a further example, with the following code we obtain randomization lists for five strata, sample sizes 35, 30, 40, 20 and 15, for 1:1:1 allocation to treatments “A”, “B” and “C”.
mergedblocksmulti(K = 5, n = c(35, 30, 40, 20, 15), ratio = c(1, 1, 1), labels = c("A", "B", "C"))
#> V1 V2 V3 V4 V5
#> 1 A A C A C
#> 2 B B B A A
#> 3 C A A C A
#> 4 C B C B B
#> 5 C C C B C
#> 6 B C B C B
#> 7 B A A A A
#> 8 A B A C B
#> 9 A C B A C
#> 10 A A A B C
#> 11 B B B C B
#> 12 C C C B C
#> 13 C C C A A
#> 14 B A B C B
#> 15 C A A A C
#> 16 A B A B <NA>
#> 17 A B B B <NA>
#> 18 B C C A <NA>
#> 19 A A B C <NA>
#> 20 B B B B <NA>
#> 21 B C A <NA> <NA>
#> 22 C C C <NA> <NA>
#> 23 C A C <NA> <NA>
#> 24 A B A <NA> <NA>
#> 25 A C C <NA> <NA>
#> 26 A B A <NA> <NA>
#> 27 C A C <NA> <NA>
#> 28 B B B <NA> <NA>
#> 29 C C A <NA> <NA>
#> 30 A A A <NA> <NA>
#> 31 B <NA> B <NA> <NA>
#> 32 B <NA> C <NA> <NA>
#> 33 B <NA> B <NA> <NA>
#> 34 C <NA> B <NA> <NA>
#> 35 A <NA> C <NA> <NA>
#> 36 <NA> <NA> A <NA> <NA>
#> 37 <NA> <NA> C <NA> <NA>
#> 38 <NA> <NA> C <NA> <NA>
#> 39 <NA> <NA> A <NA> <NA>
#> 40 <NA> <NA> A <NA> <NA>
The randomization lists can be saved using e.g. write.table()
or write.csv()
. For example:
example.list <- mergedblocksmulti(K = 5, n = c(35, 30, 40, 20, 15), ratio = c(1, 1, 1), labels = c("A", "B", "C"))
write.csv2(example.list, file = "./YourFilePath/ExampleList.csv")
This particular example will yield a CSV file with six columns. The first column contains the numbers 1-40, the remaining five columns contain the allocations per stratum (one column per stratum).