列表中的笛卡尔积

时间:2014-12-19 16:08:53

标签: r functional-programming

我有以下列表:

lst = list(
    cat = c("room","shower","garden"),
    dog = c("street", "garden")
)

我想获得输出:

list(
    list(
        animal="cat",
        place ="room"
    ),
    list(
        animal="cat",
        place ="shower"
    ),
    list(
        animal="cat",
        place ="garden"
    ),
    list(
        animal="dog",
        place ="street"
    ),
    list(
        animal="dog",
        place ="garden"
    )
)

目前,我使用以下代码:

library(plyr)

grasp <- function(animal, places)
{
    llply(places, function(u) list(animal=animal, place=u))
}

Reduce(append, Map(grasp, names(lst), lst))

但也许有更优雅/简洁/更新的东西?

2 个答案:

答案 0 :(得分:2)

这与expand.grid函数的作用非常接近;但是,它会返回一个data.frame(您可以考虑使用它)。但是转换为带有

的data.frames列表列表
# library(magrittr)
do.call(`expand.grid`, c(lst,stringsAsFactors = FALSE)) %>% split(., 1:nrow(.))

应该像你之后的行为一样

答案 1 :(得分:1)

我不知道它是否更优雅或简洁,我想它不是更新但是,它仍然可以是获得结果的另一种方式:

unlist(lapply(names(lst),function(x){
                             lapply(lst[[x]],function(y,x){
                                               list(animal=x,place=y)
                                                },x=x)
                              }),recursive=F)

我将我的解决方案和你的plyr方法放在一个列表中,每个“动物”都有1000个“动物”和50个“位置”(我尝试了更多但是我的计算机上花了太长时间。 ..)以及结果(我没有对magrittr方法进行基准测试,因为我的“虚拟”列表出错了:

base_meth<-function(){unlist(lapply(names(lst),function(x){lapply(lst[[x]],function(y,x){list(animal=x,place=y)},x=x)}),recursive=F)}

plyr_meth<-function(){Reduce(append, Map(grasp, names(lst), lst))}

microbenchmark(base_meth(),plyr_meth(),unit="relative",times=500)

 # Unit: relative
 #        expr      min       lq     mean   median       uq      max neval cld
 # base_meth() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   500  a 
 # plyr_meth() 6.885256 6.844418 5.798948 6.527788 5.475684 7.589215   500   b