在具有聚类数据的 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。然后是用替换对这些行进行采样的问题。希望我做对了。
我们可以先对每个 id
的 wave
值进行采样,然后 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 是从 id
、wave
和 variable
的所有组合中选择的.但是在这一步我们不需要所有这些组合。我将那行代码换成不那么愚蠢的代码。对不起。
我正在尝试 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。然后是用替换对这些行进行采样的问题。希望我做对了。
我们可以先对每个 id
的 wave
值进行采样,然后 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 是从 id
、wave
和 variable
的所有组合中选择的.但是在这一步我们不需要所有这些组合。我将那行代码换成不那么愚蠢的代码。对不起。