Block Randomization
Menu location: Analysis_Randomization_Blocks
This function randomizes n individuals into k treatments, in blocks of size m.
Randomization reduces opportunities for bias and confounding in experimental designs, and leads to treatment groups which are random samples of the population sampled, thus helping to meet assumptions of subsequent statistical analysis (Bland, 2000).
Random allocation can be made in blocks in order to keep the sizes of treatment groups similar. In order to do this you must specify a sample size that is divisible by the block size you choose. In turn you must choose a block size that is divisible by the number of treatment groups you specify.
An advantage of small block sizes is that treatment group sizes are very similar. A disadvantage of small block sizes is that it is possible to guess some allocations, thus reducing blinding in the trial. An alternative to using large block sizes is to use random sequences of block sizes, which is done in StatsDirect by leaving the block size blank when it is asked for. The random block size option selects block sizes of 2, 3, or 4 (at random) times the number of treatments.
The randomization proceeds by allocating random permutations of treatments within each block.
For example, to allocate 20 subjects to two treatments in blocks of random size, select Blocks from the Randomization section of the Analysis menu, enter 20 as the number of subjects, leave the block size blank, enter 2 as the number of treatments and enter 10 as the seed. StatsDirect prints:
Random allocation in blocks
Randomized with seed: 10
Subjects: 20
Block size: random between 4 and 8
Treatments: 2
| Subject | Treatment |
| 1 | A |
| 2 | A |
| 3 | B |
| 4 | B |
| 5 | B |
| 6 | B |
| 7 | A |
| 8 | A |
| 9 | A |
| 10 | A |
| 11 | B |
| 12 | A |
| 13 | B |
| 14 | B |
| 15 | B |
| 16 | A |
| 17 | B |
| 18 | A |
| 19 | B |
| 20 | A |
Each block holds the same number of subjects on each treatment, so the two groups are of equal size (10 each) here and at the end of every block. Running the function again with the same seed gives the same allocation. With the seed left blank, StatsDirect takes a seed from the computer's clock and prints it, so that the allocation can be repeated.
Technical validation
Robust (pseudo-)random number generation is used, see random number generation.
R code
This R code reproduces the illustration above in its structure: R's random number generator gives a different allocation for the same seed. It needs no packages and was checked with R 4.6.1. Paste it into R, or save it as a script and run it.
# Block randomization: the StatsDirect help illustration (20 subjects allocated to
# 2 treatments in blocks of random size, seed 10) in R
n <- 20 # subjects
t <- 2 # treatments, labelled A, B, ...
seed <- 10
if (n %% t != 0) {
stop("the number of subjects must be a multiple of the number of treatments")
}
# Each block holds the treatments in equal numbers, in an order drawn at random by
# sample(). StatsDirect and R each have their own Mersenne Twister generator and
# their own way of turning its output into a permutation, so the same seed gives a
# different allocation in R: the structure of the output is the same, the sequence
# is not. Keep the seed with the allocation, as either program can then repeat it.
set.seed(seed)
treatments <- LETTERS[1:t]
allocation <- character(0)
sizes <- integer(0)
while (length(allocation) < n) {
left <- n - length(allocation)
# a block of 2, 3 or 4 times the number of treatments, chosen at random; the
# last block takes whatever is left once fewer than 4 times t subjects remain
size <- if (left < 4 * t) left else t * sample(2:4, 1)
sizes <- c(sizes, size)
allocation <- c(allocation, sample(rep(treatments, size / t)))
}
cat("Random allocation in blocks\n")
cat("Randomized with seed:", seed, "\n")
cat("Subjects:", n, "\n")
cat("Block size: random between", 2 * t, "and", 4 * t, "\n")
cat("Treatments:", t, "\n")
print(data.frame(Subject = 1:n, Treatment = allocation), row.names = FALSE)
cat("Block sizes drawn:", sizes, "\n")
print(table(allocation))
# Blocks of one fixed size instead (4 here): n must be a multiple of the block
# size, and the block size a multiple of the number of treatments.
b <- 4
set.seed(seed)
fixed <- unlist(lapply(seq_len(n / b), function(i) sample(rep(treatments, b / t))))
cat("\nBlock size:", b, "\n")
print(data.frame(Subject = 1:n, Treatment = fixed), row.names = FALSE)