【问题标题】:In R with clustered data, how would you bootstrap at the cluster level and keep the same observation when clusters are chosen repeatedly?在具有集群数据的 R 中,当重复选择集群时,您将如何在集群级别引导并保持相同的观察?
【发布时间】:2020-02-26 20:01:49
【问题描述】:

我正在尝试从纵向数据集中引导样本,每个人有多个观察值(即随着时间的推移在多个波中收集的数据)。所以数据看起来像这样:

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 级别进行采样,并且每人只保留一个随机选择的观察值(波),但如果/当一个人被多次采样时保持相同的观察值。因此,引导程序示例可能如下所示:

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

但从不这样:

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

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

【问题讨论】:

    标签: r statistics-bootstrap


    【解决方案1】:

    您可以为随机选择的每个 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 日创建

    【讨论】:

      【解决方案2】:

      你的例子:

      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。然后就是用替换对这些行进行抽样。希望我做对了。

      【讨论】:

        【解决方案3】:

        我们可以首先为每个id 采样一个wave 值,然后inner_join 原始数据。然后我们从这个“过滤”列表中引导样本......

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

        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 的所有组合中选择的。但是在这一步我们不需要所有这些组合。我用不那么愚蠢的那行代码交换了那行代码。对不起。

        【讨论】:

          猜你喜欢
          • 2018-08-19
          • 2021-09-26
          • 2011-09-12
          • 2018-09-11
          • 2018-09-21
          • 1970-01-01
          • 2019-01-16
          • 2019-06-18
          • 1970-01-01
          相关资源
          最近更新 更多