减少具有不同长度的嵌套列表

时间:2015-03-06 08:23:59

标签: r list reduce

说我有一个清单:

  mylist=list(list(data.frame(a=3,b=2,c=4),data.frame(d=5,e=6,h=8),data.frame(k=2,e=3,b=5,m=5)),
              list(data.frame(a=32,b=22,c=42),data.frame(d=5,e=63,h=82),data.frame(k=2,e=33,b=5,m=5)),
              list(data.frame(a=33,b=21,k=41,c=41),data.frame(d=5,e=61,h=80),data.frame(k=22,e=3,b=5,m=5)))

然后我尝试按cbind列表的每个元素获取一个新列表,例如cbind mylist[[1]][[1]] mylist[[2]][[1]]mylist[[3]][[1]]

功能:

newlist=lapply(seq_along(mylist[[1]]), function(x){    
    newlist=Reduce("cbind",c(mylist[[1]][x],mylist[[-1]][x]))
    return(newlist)

})

I get:
Error in mylist[[-1]] : attempt to select more than one element  

但如果列表仅为:

,则lapply有效
mylistshort=mylist[-3]

期望的结果是:

[[1]]
  a b c  a  b  c a  b  k  c
1 3 2 4 32 22 42 33 21 41 41

[[2]]
  d e h d e  h  d e  h
1 5 6 8 5 63 82 5 61 80

[[3]]
  k e b m k e  b m k  e m
1 2 3 5 5 2 33 5 5 22 3 5

那么如何减少长度大于2的列表呢? 最诚挚的问候

4 个答案:

答案 0 :(得分:6)

另一个想法:

.mapply(cbind, mylist, NULL)
#[[1]]
#  a b c  a  b  c  a  b  k  c
#1 3 2 4 32 22 42 33 21 41 41
#
#[[2]]
#  d e h d  e  h d  e  h
#1 5 6 8 5 63 82 5 61 80
#
#[[3]]
#  k e b m k  e b m  k e b m
#1 2 3 5 5 2 33 5 5 22 3 5 5

编辑: 一些评论

基本上,你正在寻找一个“矢量化”cbind。你可以使用for循环,但R有一个内置的“矢量化”工具:mapply(不是必须更快,但更干净)。对于特定数量的参数,您可以使用mapply,如下所示:

mapply(function(x, y, z) cbind(x, y, z), mylist[[1]], mylist[[2]], mylist[[3]])

但是,你也可以通过一个“可变长度的参数”(...)来使它更实用:

mapply(function(...) cbind(...), mylist[[1]], mylist[[2]], mylist[[3]])

cbind旨在了解如何处理...个参数:

mapply(cbind, mylist[[1]], mylist[[2]], mylist[[3]])

这仍然不灵活,因为您必须指定每个参数,因为mapply仅接受...do.call对于在“列表”中有函数参数的情况很方便:

do.call(mapply, c(cbind, mylist))

R,有一个虚线mapply,它接受​​...个参数作为列表,看起来更酷,可以替换do.call

.mapply(FUN = cbind, dots = mylist, MoreArgs = NULL)

答案 1 :(得分:3)

你按照Ananda Mahto的建议做了以下(usind Reduce):

myfun <- function(x) Reduce(cbind,x)
apply(do.call(cbind, mylist), 1, myfun)

我的原始答案(包括data.table

require(data.table)
setDT(mylist)
myfun <- function(x) Reduce(cbind,x)
apply(mylist,1, myfun)

结果:

> apply(mylist,1, myfun)
[[1]]
  a b c  a  b  c  a  b  k  c
1 3 2 4 32 22 42 33 21 41 41

[[2]]
  d e h d  e  h d  e  h
1 5 6 8 5 63 82 5 61 80

[[3]]
  k e b m k  e b m  k e b m
1 2 3 5 5 2 33 5 5 22 3 5 5

答案 2 :(得分:2)

这是一种使用优质产品的方法。塑造了do.call()而不是Reduce()

lapply(
    seq_along(mylist), 
    function(ii) do.call(cbind, vapply(mylist, "[", list(1), ii))
)

# [[1]]
# a b c  a  b  c  a  b  k  c
# 1 3 2 4 32 22 42 33 21 41 41
# 
# [[2]]
# d e h d  e  h d  e  h
# 1 5 6 8 5 63 82 5 61 80
# 
# [[3]]
# k e b m k  e b m  k e b m
# 1 2 3 5 5 2 33 5 5 22 3 5 5

答案 3 :(得分:1)

另一种方法是使用unlist,如下所示:

un_mylist <- unlist(mylist, recursive = FALSE)
ind <- lapply(seq_along(mylist), seq, to = length(un_mylist), by = length(mylist))
myfun <- function(ind, x){
  Reduce(cbind,x[ind])
}
lapply(ind, myfun, x = un_mylist)

此方法假定所有嵌套列表都具有相同的长度: sapply(mylist, length)