list 在 R 中构建嵌套列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16602173/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
building nested lists in R
提问by Sam
I have written a function that it's output is a list. I want to put my function into a loop and I'd like to store output of each iteration (which is of course a list) into a bigger list. In other words, each element of this BIG list is also a list. c() does not do what I want. Is there any way to do that?
我写了一个函数,它的输出是一个列表。我想将我的函数放入一个循环中,并且我想将每次迭代的输出(当然是一个列表)存储到一个更大的列表中。换句话说,这个 BIG 列表的每个元素也是一个列表。c() 没有做我想要的。有没有办法做到这一点?
To understand better what I'm asking, consider the example below:
为了更好地理解我的要求,请考虑以下示例:
iter1 <- list(item1 = 1, item2 = "a")
iter2 <- list(item1 = 1, item2 = "b")
All <- list(iter1 = iter1, iter2 = iter2)
I want to be able to do something similar to the code above but in a loop. How can I do that?
我希望能够做一些类似于上面的代码但在循环中的事情。我怎样才能做到这一点?
Thanks for your help,
谢谢你的帮助,
回答by Frank
There's another way to assign to a list, using my_list[[name or number]] <-
. If you really want to do that in a loop, just looping over things with names like iter1, iter2, ...
还有另一种分配给列表的方法,使用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)
}
As @mnel pointed out, dynamically growing a list is inefficient. The alternative is, I think, to use lapply
:
正如@mnel 指出的那样,动态增长列表效率低下。我认为,另一种方法是使用lapply
:
n_iter <- 2
inames <- paste("iter",1:n_iter,sep="")
names(inames) <- inames
A <- lapply(inames,get)
This can also be done with a data frame, which would be a better format if your sublists always have two elements, each having a consistent class (item1 being numeric and item 2 being character).
这也可以使用数据框来完成,如果您的子列表总是有两个元素,每个元素都有一个一致的类(项目 1 是数字,项目 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
However, that's a pretty ugly way of doing things; things get messy pretty quickly when using get
. With your data structure, maybe you want to create iter1 and iter2 in a loop and immediately embed them into the parent list or data frame?
然而,这是一种非常丑陋的做事方式。使用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
}
Where anum and achar are the values of item1 and item2 you want to store from that iteration. Elsewhere on SO, they say that there is an alternative using the data.table
package that is almost 10x as fast/efficient as this sort of data-frame assignment.
其中 anum 和 achar 是您要从该迭代中存储的 item1 和 item2 的值。在 SO 的其他地方,他们说有一种替代方案使用该data.table
包,其速度/效率几乎是这种数据帧分配的 10 倍。
Oh, one last idea: if you want to put them in a list first, you can easily convert to a data frame later with
哦,最后一个想法:如果你想先把它们放在一个列表中,你可以稍后轻松地转换为数据框
DF <- do.call(rbind.data.frame,A)
回答by Ricardo Saporta
This gets you the equivalent of your All
这让你相当于你的 All
c(iter1=list(iter1), iter2=list(iter2))
> identical(c(iter1=list(iter1), iter2=list(iter2)), All)
[1] TRUE
Let's say you'd like to add a third list to All
:
假设您想将第三个列表添加到All
:
c(All, list(iter3=iter3))
If you don't care for the list names, it looks a little cleaner
如果你不关心列表名称,它看起来更干净一些
c(list(iter1), list(iter2))
回答by Simon O'Hanlon
I think @Frank's answer is the correct one here, but the first example he gave seemed a little strange. I think you want to do this...
我认为@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"
but you should consider the alternatives by Frank if possible.
但如果可能,您应该考虑 Frank 的替代方案。
回答by omarflorez
This worked for me very well, hope it helps.
这对我来说非常有效,希望它有所帮助。
data = list()
for(i in 1:3)
{
tmp = c(1,2,3)
data = rbind(data, tmp)
}