R语言简单随机分组分块随机化分层随机化

关注公众号,发送R语言或python获取资料

重点关注R语言在生物医学中的运用

随机分组在临床设计中太常见了。 临床上常用的随机分组方法有四种:

当然,还有其他类型。 关于随机分组的问题,推荐大家看一下医学咖啡俱乐部的这篇文章:10篇文章,全面理解随机分组。 赶快收藏起来吧! [1]

本文主要介绍如何使用R语言完成随机分组。

简单随机化,也称为完全随机化,是最简单的随机分组方法。 在医学统计中,我们经常会遇到完全随机设计的xxx,指的是简单随机分组!

比如,病人来了,抛硬币,根据正面和反面随机决定进入实验组还是对照组。 然而,实际操作却没有那么随意。 每个人都只是通过随机数字表方法或软件随机分组。 原理几乎是一样的。

如果需要收集100名受试者,随机分为实验组和对照组,可以按照每位患者入院的顺序给其编号,然后从随机编号表的任意行或列开始并抽取一个随机数, 100 每个科目有 100 个随机数。 将这 100 个随机数从小到大排序。 前50名进入实验组,后50名进入对照组(余数、单双数等也可以)。

上述方法可以通过SPSS来实现。 可以参考这篇文章:SPSS实现简单随机分组[2]

按照这个思路,R语言也可以实现。 R语言在临床研究设计中的使用已经非常成熟。 Cran 任务视图中有两个关于研究设计的主题。 如果您有兴趣,可以自己看一下。

简单随机

例如,将30人按照完全随机的方法分为2组,实验组和对照组,每组15人。

id <- c(1:30)
group <- rep(c("试验组","对照组"),15)
rand <- sample(group, 30, replace = T)
(res <- cbind(id, group))
##       id   group   
##  [1,] "1"  "试验组"
##  [2,] "2"  "对照组"
##  [3,] "3"  "试验组"
##  [4,] "4"  "对照组"
##  [5,] "5"  "试验组"
##  [6,] "6"  "对照组"
##  [7,] "7"  "试验组"
##  [8,] "8"  "对照组"
##  [9,] "9"  "试验组"
## [10,] "10" "对照组"
## [11,] "11" "试验组"
## [12,] "12" "对照组"
## [13,] "13" "试验组"
## [14,] "14" "对照组"
## [15,] "15" "试验组"
## [16,] "16" "对照组"
## [17,] "17" "试验组"
## [18,] "18" "对照组"
## [19,] "19" "试验组"
## [20,] "20" "对照组"
## [21,] "21" "试验组"
## [22,] "22" "对照组"
## [23,] "23" "试验组"
## [24,] "24" "对照组"
## [25,] "25" "试验组"
## [26,] "26" "对照组"
## [27,] "27" "试验组"
## [28,] "28" "对照组"
## [29,] "29" "试验组"
## [30,] "30" "对照组"

 

我们还可以通过 randomizr 包来实现这一点。 如果没有安装,需要先安装。

install.packages("randomizr")

 

“抛硬币”风格的简单随机分组是通过 simple_ra() 函数实现的:

library(randomizr)

# 100人分2组
sim <- simple_ra(100, num_arms = 2, conditions = c("试验组","对照组"))

sim
##   [1] 试验组 对照组 对照组 对照组 对照组 试验组 试验组 对照组 对照组 对照组
##  [11] 对照组 试验组 对照组 对照组 试验组 试验组 对照组 对照组 对照组 试验组
##  [21] 试验组 试验组 试验组 对照组 试验组 对照组 试验组 对照组 试验组 试验组
##  [31] 试验组 对照组 对照组 试验组 对照组 试验组 对照组 试验组 试验组 试验组
##  [41] 试验组 试验组 对照组 对照组 对照组 试验组 试验组 试验组 试验组 对照组
##  [51] 对照组 试验组 对照组 对照组 对照组 对照组 试验组 对照组 试验组 试验组
##  [61] 试验组 对照组 对照组 试验组 试验组 试验组 对照组 试验组 对照组 试验组
##  [71] 对照组 试验组 试验组 对照组 试验组 对照组 对照组 对照组 对照组 试验组
##  [81] 对照组 对照组 试验组 试验组 试验组 对照组 试验组 试验组 试验组 对照组
##  [91] 试验组 试验组 对照组 试验组 试验组 试验组 试验组 试验组 对照组 对照组
## Levels: 试验组 对照组
table(sim)
## sim
## 试验组 对照组 
##     53     47

 

但这种分组最大的问题是分组人数不同,在临床研究设计中通常是1:1。 我们可以使用另一个函数来解决这个问题。

com <- complete_ra(100, num_arms = 2, conditions = c("试验组","对照组"))

com
##   [1] 对照组 试验组 对照组 试验组 试验组 对照组 试验组 对照组 试验组 对照组
##  [11] 试验组 对照组 对照组 对照组 试验组 对照组 对照组 试验组 对照组 试验组
##  [21] 对照组 试验组 对照组 对照组 试验组 试验组 对照组 对照组 试验组 对照组
##  [31] 对照组 试验组 对照组 对照组 对照组 对照组 对照组 试验组 试验组 对照组
##  [41] 试验组 试验组 对照组 对照组 试验组 试验组 对照组 对照组 试验组 对照组
##  [51] 对照组 试验组 试验组 试验组 试验组 试验组 试验组 试验组 试验组 对照组
##  [61] 对照组 对照组 试验组 试验组 对照组 试验组 对照组 对照组 试验组 对照组
##  [71] 对照组 试验组 试验组 对照组 对照组 试验组 试验组 试验组 对照组 试验组
##  [81] 试验组 对照组 对照组 对照组 试验组 试验组 对照组 试验组 试验组 试验组
##  [91] 试验组 试验组 对照组 试验组 对照组 对照组 试验组 对照组 试验组 对照组
## Levels: 试验组 对照组
table(com)
## com
## 试验组 对照组 
##     50     50

 

完美解决群体间人数不对等的问题。

网上的高手也给出了自己写的函数:

simple_random <- function(size, grp = 2, T_2_C = "1:1"){
    set.seed(20210412)
    id_num <- seq(1, size, 1)
    random_seq <- runif(n = size, min = 0, max = 1)
    int_rank <- rank(random_seq)
    
    ratio_T <- as.numeric(substr(T_2_C, 11))
    ratio_C <- as.numeric(substr(T_2_C, 33))
    
    if (grp == 2) {
        group <- ifelse(int_rank <= size/(ratio_T + ratio_C), "T""C")
    } else if (grp > 3) {
        group <- cut(int_rank, breaks = grp, labels = paste("Group"1:grp))
    }
    
    df <- data.frame("ID" = id_num, "RandomNum" = random_seq, 
                        "Rank" = int_rank, "Group" = group)
    
    #write.csv(df, "simple randomization table.csv", row.names = FALSE)
    
    return(df)
}

 

20人随机分为几组:

simple_random(20)
##    ID  RandomNum Rank Group
## 1   1 0.83237492   19     C
## 2   2 0.95522177   20     C
## 3   3 0.59787880   10     T
## 4   4 0.35076793    4     T
## 5   5 0.43157421    6     T
## 6   6 0.63326323   13     C
## 7   7 0.78015581   17     C
## 8   8 0.46990952    7     T
## 9   9 0.38535395    5     T
## 10 10 0.63361183   14     C
## 11 11 0.73655082   15     C
## 12 12 0.49675139    8     T
## 13 13 0.61201021   11     C
## 14 14 0.23511285    3     T
## 15 15 0.52894214    9     T
## 16 16 0.04290597    1     T
## 17 17 0.74367251   16     C
## 18 18 0.79647582   18     C
## 19 19 0.62653890   12     C
## 20 20 0.22537775    2     T

 

另外,有很多R包可以实现随机分组,包括但不限于简单随机分组/分块随机化/分层随机化等。

块随机

您可以使用 randomizr 来实现块随机化:

# Load built-in dataset
data(HairEyeColor)
HairEyeColor <- data.frame(HairEyeColor)

# Transform so each row is a subject
# Columns describe subjects hair color, eye color, and gender
hec <- HairEyeColor[rep(1:nrow(HairEyeColor),
                        times = HairEyeColor$Freq), 1:3]

N <- nrow(hec)

# Fix the rownames
rownames(hec) <- NULL
dim(hec)
## [1] 592   3
head(hec)
##    Hair   Eye  Sex
## 1 Black Brown Male
## 2 Black Brown Male
## 3 Black Brown Male
## 4 Black Brown Male
## 5 Black Brown Male
## 6 Black Brown Male

 

根据头发颜色进入不同的组,然后分为3组:

Z <- block_ra(blocks = hec$Hair, conditions = c("Control""Placebo""Treatment"))
table(Z, hec$Hair)
##            
## Z           Black Brown Red Blond
##   Control      36    95  24    42
##   Placebo      36    96  23    42
##   Treatment    36    95  24    43

 

您可以自由控制组数:

sort(unique(hec$Hair))
## [1] Black Brown Red   Blond
## Levels: Black Brown Red Blond
block_m_each <- rbind(c(7830),
                      c(186100),
                      c(5120),
                      c(87,40))

block_m_each
##      [,1] [,2]
## [1,]   78   30
## [2,]  186  100
## [3,]   51   20
## [4,]   87   40
Z <- block_ra(blocks = hec$Hair, block_m_each = block_m_each)
table(Z, hec$Hair)
##    
## Z   Black Brown Red Blond
##   0    78   186  51    87
##   1    30   100  20    40

 

然而,这种分组随机化不太适合临床研究,因为这里的情况需要所有受试者提前做好准备,然后进行分组。 对于临床研究来说,受试者是一一来的,并不是一下子全部都有的,所以block_ra()可能更适合动物实验或者基础研究分组。 关于分块随机化的更多知识,可以参考医学咖啡协会的这篇文章:一篇文章详细讲解分块随机化,包括教育和理解! [3]

通过blockrand包可以实现临床研究的随机分组,特别适合一次招募一个人的临床研究!

例如,100人随机分为2组,每组50人:

library(blockrand)

set.seed(111)
res <- blockrand(n=100, num.levels = 2, levels = c("试验组","对照组"))
head(res)
##   id block.id block.size treatment
## 1  1        1          4    试验组
## 2  2        1          4    对照组
## 3  3        1          4    试验组
## 4  4        1          4    对照组
## 5  5        2          6    试验组
## 6  6        2          6    试验组

# 结果并不是50 50,因为block size不一样
table(res$treatment)
## 
## 对照组 试验组 
##     51     51

 

您还可以帮助我们生成 PDF 文。