从 R 中的嵌套列表中的每个列表中采样 1 个元素以创建样本组

sample 1 element from each list in nested list in R to create groups of samples

我有一个嵌套的列表列表,其中每个条目都包含一个值列表。

我希望从每个嵌套列表中抽取一个元素并创建一组元素。

此类列表的示例是:

xxx_ <- list(c(13L, 15L, 5L, 6L), c(7L, 20L, 14L, 18L, 1L, 8L, 17L), 
    c(9L, 11L, 4L, 12L), c(16L, 19L, 10L, 2L, 3L))

我正在执行以下操作,但感觉需要有一种更简单的方法来对这个列表列表进行抽样。

l_sample <- list()
for(g in 1:10) {
  l <- c()
  for(i in 1:4) {
    l <- c(l,sample(xxx_[[i]], 1))
  }
  l_sample[[g]] <- l
}

结果如下:

> l_sample
[[1]]
[1] 15  7 12 10

[[2]]
[1] 6 1 4 2

[[3]]
[1] 13 18  4 19

[[4]]
[1]  6 17  4  2

[[5]]
[1] 15 18  4  3

[[6]]
[1] 13 18  9  3

[[7]]
[1]  6 17 12 19

[[8]]
[1]  5 20  9 19

[[9]]
[1]  5 18  9 10

[[10]]
[1] 13  7  9  3

我还想将每个样本作为新行附加到数据框,其中每个元素都在新列中,但我做不到。

类似于:

> df
  g1 g2 g3 g4
1 15  7 12 10
2 6 1 4 2
...

非常感谢您的帮助。

您可以使用 sapply 到每个列表中的 select 1 个元素,然后使用 replicate 重复 10 次。

t(replicate(10, sapply(xxx_, sample, 1)))

#      [,1] [,2] [,3] [,4]
# [1,]   15    7    9   10
# [2,]   15    8    9    3
# [3,]   13   14    4   19
# [4,]    5   14   12   10
# [5,]   13   20    9    3
# [6,]    5   18   12   16
# [7,]    5    1   11    2
# [8,]    6   14   11   19
# [9,]    5    8   12    3
#[10,]    5   17    4    2

如果你想从每个嵌套列表中采样 10 次,那么你可以将 size = 10replace = TRUE 像这样传递给 sample 使用 sapply:

set.seed(1)
sapply(xxx_, sample, 10, TRUE)
#R>       [,1] [,2] [,3] [,4]
#R>  [1,]   13   14    9   19
#R>  [2,]    6   14    4   16
#R>  [3,]    5    7    9    2
#R>  [4,]   13    1    9   16
#R>  [5,]   15    1    9    2
#R>  [6,]   13   20    9   10
#R>  [7,]    5    8   11   19
#R>  [8,]    5    8    9   19
#R>  [9,]   15   20    9    2
#R> [10,]   15   17   11    2

10 更改为您要抽取的次数。

这种方法的另一个优点是它会保留名称。例如,假设您的数据如下所示:

xxx_ <- list(
  g1 = c(13L, 15L, 5L, 6L ), g2 = c(7L , 20L, 14L, 18L, 1L, 8L, 17L), 
  g3 = c(9L , 11L, 4L, 12L), g4 = c(16L, 19L, 10L, 2L, 3L))

然后您可以按照您的要求执行以下操作以获得 data.frame:

set.seed(1)
as.data.frame(sapply(xxx_, sample, 10, TRUE))
#R>    g1 g2 g3 g4
#R> 1  13 14  9 19
#R> 2   6 14  4 16
#R> 3   5  7  9  2
#R> 4  13  1  9 16
#R> 5  15  1  9  2
#R> 6  13 20  9 10
#R> 7   5  8 11 19
#R> 8   5  8  9 19
#R> 9  15 20  9  2
#R> 10 15 17 11  2

速度

比调用replicate:

快多了
bench::mark(
    replicate = t(replicate(10, sapply(xxx_, sample, 1))), 
    sapply    = sapply(xxx_, sample, 10, TRUE), 
    min_time = 1, check = FALSE)
#R> # A tibble: 2 x 13
#R>   expression      min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result memory                  time              gc                   
#R>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm> <list> <list>                  <list>            <list>               
#R> 1 replicate   213.3µs    235µs     4071.   100.3KB     45.7  3384    38      831ms <NULL> <Rprofmem[,3] [43 × 3]> <bch:tm [3,422]>  <tibble [3,422 × 3]> 
#R> 2 sapply       22.4µs   25.2µs    38417.    10.4KB     46.2  9988    12      260ms <NULL> <Rprofmem[,3] [6 × 3]>  <bch:tm [10,000]> <tibble [10,000 × 3]>