我写了一个函数,它的输出是一个列表。我想把我的函数放到一个循环中,我想将每个迭代的输出(当然是列表)存储到一个更大的列表中。换句话说,这个BIG列表的每个元素也是一个列表。 c()没有做我想要的。有没有办法做到这一点?
为了更好地理解我的要求,请考虑以下示例:
iter1 <- list(item1 = 1, item2 = "a")
iter2 <- list(item1 = 1, item2 = "b")
All <- list(iter1 = iter1, iter2 = iter2)
我希望能够在循环中执行类似于上面代码的操作。我怎么能这样做?
感谢您的帮助,
答案 0 :(得分:7)
还有另一种使用my_list[[name or number]] <-
分配给列表的方法。如果你真的想在一个循环中这样做,只需使用iter1,iter2等名称循环...
A <- list()
n_iter <- 2
for (i in 1:n_iter){
iname <- paste("iter",i,sep="")
A[[iname]] <- get(iname)
}
正如@mnel指出的那样,动态增长列表是低效的。我认为,替代方案是使用lapply
:
n_iter <- 2
inames <- paste("iter",1:n_iter,sep="")
names(inames) <- inames
A <- lapply(inames,get)
这也可以通过数据框来完成,如果你的子列表总是有两个元素,每个元素都有一个一致的类(item1是数字,第2项是字符),这将是一个更好的格式。
n_iter <- 2
DF <- data.frame(item1=rep(0,n_iter),item2=rep("",n_iter),stringsAsFactors=FALSE)
for (i in 1:n_iter){
iname <- paste("iter",i,sep="")
DF[i,] <- get(iname)
rownames(DF)[i] <- iname
}
# item1 item2
# iter1 1 a
# iter2 1 b
然而,这是一种非常丑陋的做事方式;使用get
时,事情会很快变得混乱。使用您的数据结构,您是否希望在循环中创建iter1和iter2并立即将它们嵌入到父列表或数据框中?
n_iter = 10
DF <- data.frame(item1 = rep(0,n_iter), item2 = rep("",n_iter))
for (i in 1:n_iter){
... do stuff to make anum and achar ...
DF[i,"item1"] <- anum
DF[i,"item2"] <- achar
}
其中anum和achar是要从该迭代存储的item1和item2的值。 Elsewhere on SO,他们说有一个使用data.table
包的替代方案,其速度/效率几乎是这种数据帧分配的10倍。
哦,最后一个想法:如果你想先把它们放在一个列表中,你可以稍后用
轻松转换为数据框DF <- do.call(rbind.data.frame,A)
答案 1 :(得分:5)
这相当于你的All
c(iter1=list(iter1), iter2=list(iter2))
> identical(c(iter1=list(iter1), iter2=list(iter2)), All)
[1] TRUE
假设您要将第三个列表添加到All
:
c(All, list(iter3=iter3))
如果您不关心列表名称,它看起来会更清晰
c(list(iter1), list(iter2))
答案 2 :(得分:1)
我认为@Frank的答案在这里是正确的,但他给出的第一个例子似乎有点奇怪。我想你想这样做......
bigLL <- list()
for( i in 1:3 ){
ll <- list( item1 = i , item2 = letters[i] )
bigLL[[i]] <- ll
}
bigLL
#[[1]]
#[[1]]$item1
#[1] 1
#[[1]]$item2
#[1] "a"
#[[2]]
#[[2]]$item1
#[1] 2
#[[2]]$item2
#[1] "b"
#[[3]]
#[[3]]$item1
#[1] 3
#[[3]]$item2
#[1] "c"
但如果可能的话,你应该考虑Frank的替代方案。
答案 3 :(得分:-1)
这对我很有用,希望它有所帮助。
data = list()
for(i in 1:3)
{
tmp = c(1,2,3)
data = rbind(data, tmp)
}