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

问题描述

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

我希望从每个嵌套列表中采样一个元素,并创建一组元素。

此类列表的一个示例是:

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从每个列表中选择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 = TRUEsample传递给sapply

set.seed(1)
sapply(xxx_,10,TRUE)
#R>       [,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_,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,1))),sapply    = sapply(xxx_,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]>