在具有聚类数据的 R 中,您如何在聚类级别 bootstrap 并在重复选择聚类时保持相同的观察结果?

In R with clustered data, how would you bootstrap at the cluster level and keep the same observation when clusters are chosen repeatedly?

我正在尝试 bootstrap 从纵向数据集中对每个人进行多次观察(即随时间在多个波中收集的数据)的纵向数据集进行采样。所以数据看起来像这样:

id     wave   variable
101    1      15
101    2      17
101    3      18
102    1      13
102    2      14
102    3      14
103    1      13
103    2      15
103    3      17

我想做的是在 PERSON 级别进行抽样,每个人只保留一个随机选择的观察(波),但保持相同的观察 if/when 对一个人进行多次抽样。所以 bootstrap 示例可能如下所示:

id     wave   variable
101    1      15
103    2      15
101    1      15 

但绝不会这样:

id     wave   variable
101    1      15
103    2      15
101    2      17

我一直在为如何编写代码而苦苦挣扎,更不用说优雅地编写代码了。任何想法将不胜感激。

您可以得到一个数据框,每个 ID 随机选择一行,然后只需对该数据框进行替换采样:

set.seed(69)
dfs <- split(df, df$id)
dfs <- mapply(function(x, y) x[sample(y,1),], dfs, sapply(dfs, nrow), SIMPLIFY = FALSE)
result <- do.call(rbind, dfs)
result[sample(nrow(result), 9, TRUE), ]
#>        id wave variable
#> 101   101    1       15
#> 103   103    2       15
#> 103.1 103    2       15
#> 103.2 103    2       15
#> 102   102    3       14
#> 101.1 101    1       15
#> 103.3 103    2       15
#> 102.1 102    3       14
#> 102.2 102    3       14

reprex package (v0.3.0)

于 2020 年 2 月 26 日创建

你的例子:

x = structure(list(id = c(101L, 101L, 101L, 102L, 102L, 102L, 103L, 
103L, 103L), wave = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), variable = c(15L, 
17L, 18L, 13L, 14L, 14L, 13L, 15L, 17L)), class = "data.frame", row.names = c(NA, 
-9L))

也许是这样的,如果你不介意 dplyr:

set.seed(111)
x %>% group_by(id) %>% sample_n(1) %>%  
ungroup() %>% sample_n(n(),replace=TRUE)

# A tibble: 3 x 3
     id  wave variable
  <int> <int>    <int>
1   103     3       17
2   101     2       17
3   103     3       17

在第一行中,您按 id 分组,并采样 1。接下来取消分组,因此您只有唯一的 id。然后是用替换对这些行进行采样的问题。希望我做对了。

我们可以先对每个 idwave 值进行采样,然后 inner_join 原始数据。然后我们 bootstrap 从这个 'filtered' 列表中抽样...

创建更大的数据集以重现采样:

set.seed(13)
df <- data.frame(id = rep(101:103, each=9),
                 wave = rep(1:3, times=9),
                 variable = sample(1:20,9*3, TRUE))

head(df)
   id wave variable
1 101    1        4
2 101    2        2
3 101    3        1
4 101    1       19
5 101    2       19
6 101    3       17

使用dplyr的解决方案:

library(dplyr)

  boot_size = 1000

boot <- df %>% 
  inner_join(df %>% 
               group_by(id, ) %>% 
               sample_n(1) %>% 
               select(id, wave)) %>% 
  sample_n(boot_size, replace = TRUE)

测试是否有效:

  head(boot)
   id wave variable
1 101    2        5
2 103    3        4
3 102    3       11
4 103    3        3
5 103    3        3
6 101    2        6
table(boot$id, boot$wave)
      2   3
101 323   0
102   0 353
103   0 324

看起来不错,每个 id 的值都来自一个 wave

编辑:

我不小心发布了一个有效但非常低效且愚蠢的解决方案版本,其中我的加入 data.frame 是从 idwavevariable 的所有组合中选择的.但是在这一步我们不需要所有这些组合。我将那行代码换成不那么愚蠢的代码。对不起。