基于多种因素的Bootstrap采样

时间:2018-03-15 22:28:13

标签: r dplyr

我有一个类似于此的数据框:

   Factor1 Factor2      Value
1        A       1 -0.1169027
2        B       1  0.4153005
3        B       2 -1.8824073
4        B       3  0.2627502
5        C       1  0.8822784
6        C       2  0.5011568
7        C       3  0.2332566
8        C       4  0.1897866
9        C       5 -1.4404080
10       C       6  0.3414159

我感兴趣的是编写一段代码,根据Factor2中不同样本的最大数量,存储在每个Factor1级别的新数据帧bootstrap样本中。

library(tidyverse)    
sampleGroups <- df %>%
        group_by(Factor1) %>%
        select(Factor1, Factor2) %>%
        summarise(n_distinct(Factor2))
    sampleGroups ## max = 6

一旦选择了Factor1的每个级别中的所有独特的Factor2水平,样本都需要更换。

因此上表的合适输出如下所示:

   Factor1 Factor2      Value
1        A       1 -0.1169027
2        A       1 -0.1169027
3        A       1 -0.1169027
4        A       1 -0.1169027
5        A       1 -0.1169027
6        A       1 -0.1169027
7        B       1  0.4153005
8        B       2  1.8824073
9        B       3  0.2627502
10       B       1  0.4153005
11       B       2 -1.8824073
12       B       2 -1.8824073
13       C       1  0.8822784
14       C       2  0.5011568
15       C       3  0.2332566
16       C       4  0.1897866
17       C       5 -1.4404080
18       C       6  0.3414159

当你可以看到因子1 = A重复6次时,因子1 = B重复6次,但因子1(B)中的因子2在因子1(B)中选择因子2的所有水平后被重复引导,然后选择因子1(C)6次,因为这是发现最高数量的因子2的独特水平。

我的真实数据集有20个Factor1级别,17个独特级别的Factor2嵌套在Factor1中。

这样的事情在R中很容易实现吗?也许使用dplyr?我有一些代码可以从Factor2中为Factor1的每个级别随机选择一个样本,但我无法弄清楚如何强制它为Factor1的每个级别选择所有级别的Factor2(必要时)。

dfBoot <- tibble(Bootstrap = integer(0), Factor1 = character(0), Factor2 = character(0))
for (i in 1:10) {
    selected <- df %>%
        group_by(Factor1) %>%
        select(Factor1, Factor2) %>%
        sample_n(1) %>%
        mutate(Bootstrap = i)
    dfBoot <- bind_rows(dfBoot, selected)
}
dfBoot
# A tibble: 30 x 3
   Bootstrap Factor1 Factor2
       <int> <chr>   <chr>  
 1         1 A       1      
 2         1 B       2      
 3         1 C       1      
 4         2 A       1      
 5         2 B       1      
 6         2 C       5      
 7         3 A       1      
 8         3 B       2      
 9         3 C       3      
10         4 A       1      
# ... with 20 more rows

replace = TRUE添加到上面的sample_n行,会产生一个具有正确样本数的数据帧,但每个级别的因子2都是随机采样的,我需要将替换只发生一次已经选择了所有级别的因子2。

dfBoot <- tibble(Bootstrap = integer(0), Factor1 = character(0), Factor2 = character(0))
for (i in 1:10) {
    selected <- df %>%
        group_by(Factor1) %>%
        select(Factor1, Factor2) %>%
        # sample with replacement this time
        sample_n(6, replace = TRUE) %>%
        mutate(Bootstrap = i)
    dfBoot <- bind_rows(dfBoot, selected)
}

# A tibble: 180 x 3
   Bootstrap Factor1 Factor2
       <int> <chr>   <chr>  
 1         1 A       1      
 2         1 A       1      
 3         1 A       1      
 4         1 A       1      
 5         1 A       1      
 6         1 A       1      
 7         1 B       1      
 8         1 B       3      
 9         1 B       2      
10         1 B       2      
# ... with 170 more rows
dfBoot

1 个答案:

答案 0 :(得分:1)

这应该可以解决问题。我们的想法是将数据拆分为Factor1,然后rbind将每个拆分拆分为重新采样,其大小为原始数据集中Factor1的最大数量与因子数之差在每次拆分中Factor1

df %>%
  mutate(max_n = max(Factor2)) %>%
  split(.$Factor1) %>%
  map_dfr(~rbind(., sample_n(., if(max(.$Factor2) == mean(.$max_n)) 0 else(mean(.$max_n) - max(.$Factor2)), replace = TRUE))) %>%
  select(-max_n)

#    Factor1 Factor2   Value
# 1        A       1 -0.1169
# 2        A       1 -0.1169
# 3        A       1 -0.1169
# 4        A       1 -0.1169
# 5        A       1 -0.1169
# 6        A       1 -0.1169
# 7        B       1  0.4153
# 8        B       2 -1.8824
# 9        B       3  0.2628
# 10       B       1  0.4153
# 11       B       1  0.4153
# 12       B       1  0.4153
# 13       C       1  0.8823
# 14       C       2  0.5012
# 15       C       3  0.2333
# 16       C       4  0.1898
# 17       C       5 -1.4404
# 18       C       6  0.3414