我有两个嵌套的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.tables。
我已经读过here和here,发现使用assign(.)
的设置不是非常Rly,我想知道是否可以改进。
一方面,我喜欢对j循环的列表进行编号,这样我就可以将它们与加载到此处的数据集相关联(此处为模拟)。另一方面,i循环可以产生一个列表列表,但是我想知道除可伸缩性之外还有什么好处。
答案 0 :(得分:3)
列表列表非常好并且易于使用。但是,模式“列表”的矩阵可以是非常方便的替代方法:
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
答案 1 :(得分:1)
使用基本的R *pply*
系列函数或map_*
中的purrr
系列函数对您都非常有益。这是使用基数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)
),然后用lapply
或map
浏览所有结果。
说,您想从20个副本中的每个副本中获取第一个j
索引:
j1 <- map(res, ~ .[[1]])
哦,您想要在一个数据帧中全部完成吗?
j1 <- map_dfr(res, ~ .[[1]])
第二个优点:您立即看到代码已损坏。对于每个i,您都会生成100个随机数(perm
),但是您只使用过一个...每个i
都有一个! (perm[i]
,代表1..20中的i)。为什么根本需要100个?