列表优于编号 data.tables

advantage of list over numbered data.tables

我有两个嵌套的 for 循环,我在每个循环中加载(这里模拟)和操作数据,以创建多个列表。

library(data.table)
for(i in 1:20){
    perm <- rnorm(1); res <- list()
    for(j in 1:500){
        temp <- runif(5,0,20)
        res[[j]] <- data.table(a=temp/perm, b=temp+perm)
    }
    assign(paste0("x",i),res); rm(res)
}

因为内部 for 循环输出 data.table,我在外部 for 循环的每次迭代中创建一个列表来保存内部循环产生的不同 data.table。

我读到 here and here 使用 assign(.) 的设置不是很方便,我想知道这是否可以改进。

一方面,我喜欢对 j 循环列表进行编号,这样我就可以将它们与加载到那里的数据集相关联(这里是模拟的)。另一方面,i-loop 可以生成列表列表,但我想知道除了可伸缩性之外还有什么优势。

使用基本 R *pply* 函数族或 purrr 中的 map_* 族函数对您有很大帮助。这是您使用基本 R 的代码:

res <- lapply(1:20, function(i) {
  perm <- rnorm(100)
  ret <- lapply(1:500, function(j) {
         temp <- runif(5, 0, 20)
         data.frame(a=temp/perm[i], b=temp+perm[i])
      })
})

优点:无需填充当前环境,您有一个对象 (res),您可以使用循环等轻松操作该对象。将结果存储在列表中的最直接优势是方便。您可以一次保存所有结果 (save(res, file="res.rda")),计算您有多少 (length(res)),用 lapplymap 浏览它们。

比如说,您想从 20 个重复中的每一个中获取第一个 j 索引:

j1 <- map(res, ~ .[[1]])

哦,你想把所有的都放在一个数据框中吗?

j1 <- map_dfr(res, ~ .[[1]])

第二个优势:您会立即发现您的代码有问题。对于每个 i,您生成 100 个随机数 (perm),但您只使用...其中一个用于每个 i! (perm[i],对于 1..20 中的 i)。为什么你需要 100 个?

列表的列表很好用,也很容易使用。但是,模式矩阵 "list" 可能是一个非常方便的替代方案:

m <- 2
n <- 3
res <- vector(length = m * n, mode = "list")
res <- matrix(res, ncol = m)

library(data.table)
for(i in 1:n){
  perm <- rnorm(100)
  for(j in 1:m){
    temp <- runif(5,0,20)
    res[i,j] <- list(data.table(a=temp/perm[i], b=temp+perm[i]))
  }
}

res[1,] #result from first iteration of outer loop
#[[1]]
#            a         b
#1:  -6.434118  7.744621
#2:  -7.741497  9.607878
#3:  -3.200882  3.136663
#4:  -8.283567 10.380427
#5: -10.989466 14.236833
#
#[[2]]
#            a         b
#1: -12.045692 15.742150
#2: -13.199384 17.386375
#3:  -6.176316  7.377206
#4: -13.549293 17.885059
#5:  -3.025583  2.886829