Multiplying Combinations of a list of lists in R

前端 未结 4 1471
孤城傲影
孤城傲影 2020-12-07 02:37

Given a list of two lists, I am trying to obtain, without using for loops, a list of all element-wise products of the first list with the second. For example:



        
4条回答
  •  萌比男神i
    2020-12-07 02:57

    Pulling ideas from the other answers together, I'll throw another one-liner in for fun:

    do.call(mapply, c(FUN=`*`, as.list(expand.grid(b, a))))
    

    which gives

         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
    [1,]    1    3    6    2    6   12    4   12   24
    [2,]    6    8    4    9   12    6   15   20   10
    

    If you really need it in the format you gave, then you can use the plyr library to transform it into that:

    library("plyr")
    as.list(unname(alply(do.call(mapply, c(FUN=`*`, as.list(expand.grid(b, a)))), 2)))
    

    which gives

    [[1]]
    [1] 1 6
    
    [[2]]
    [1] 3 8
    
    [[3]]
    [1] 6 4
    
    [[4]]
    [1] 2 9
    
    [[5]]
    [1]  6 12
    
    [[6]]
    [1] 12  6
    
    [[7]]
    [1]  4 15
    
    [[8]]
    [1] 12 20
    
    [[9]]
    [1] 24 10
    

    Just for fun, benchmarking:

    Joris <- function(a, b) {
        mapply(`*`,a,rep(b,each=length(a)))
    }
    
    TylerM <- function(a, b) {
        x <- expand.grid(1:length(a), 1:length(b))
        x <- x[order(x$Var1), ]    #gives the order you asked for
        FUN <- function(i)  diag(outer(a[[x[i, 1]]], b[[x[i, 2]]], "*"))
        sapply(1:nrow(x), FUN)
    }
    
    TylerL <- function(a, b) {
        x <- expand.grid(1:length(a), 1:length(b))
        x <- x[order(x$Var1), ]    #gives the order you asked for
        FUN <- function(i)  diag(outer(a[[x[i, 1]]], b[[x[i, 2]]], "*"))
        lapply(1:nrow(x), FUN)
    }
    
    Wojciech <- function(a, b) {
        # Matrix with indicies for elements to multiply
        G <- expand.grid(1:3,1:3)
    
        # Coversion of G to list
        L <- lapply(1:nrow(G),function(x,d=G) d[x,])
    
        lapply(L,function(i,x=a,y=b) x[[i[[2]]]]*y[[i[[1]]]])
    }
    
    DiggsM <- function(a, b) {
        do.call(mapply, c(FUN=`*`, as.list(expand.grid(b, a))))
    }
    
    DiggsL <- function(a, b) {
        as.list(unname(alply(t(do.call(mapply, c(FUN=`*`, as.list(expand.grid(b, a))))), 1)))
    }
    

    and the benchmarks

    > library("rbenchmark")
    > benchmark(Joris(b,a),
    +           TylerM(a,b),
    +           TylerL(a,b),
    +           Wojciech(a,b),
    +           DiggsM(a,b),
    +           DiggsL(a,b),
    +           order = "relative", 
    +           replications = 1000,
    +           columns = c("test", "elapsed", "relative"))
                test elapsed relative
    1    Joris(b, a)    0.08    1.000
    5   DiggsM(a, b)    0.26    3.250
    4 Wojciech(a, b)    1.34   16.750
    3   TylerL(a, b)    1.36   17.000
    2   TylerM(a, b)    1.40   17.500
    6   DiggsL(a, b)    3.49   43.625
    

    and to show they are equivalent:

    > identical(Joris(b,a), TylerM(a,b))
    [1] TRUE
    > identical(Joris(b,a), DiggsM(a,b))
    [1] TRUE
    > identical(TylerL(a,b), Wojciech(a,b))
    [1] TRUE
    > identical(TylerL(a,b), DiggsL(a,b))
    [1] TRUE
    

提交回复
热议问题