重叠多个参数,更快的方法

时间:2018-07-25 09:22:48

标签: r apply lapply mapply

假设我有两个向量

 a <- c(1,2,3,4,5)
 b <- c(6,7,8,9,10)

和一个功能

calc <- function(x,y){x + y)

我想将此功能应用于a中每个值的b中的第一个值。假设在我的情况下,calc仅允许来自ab的单个值作为输入,因此lapply(a,calc,b)将不起作用,因为length(b)不是1,则(给我一个错误)。

mapply也不给我想要的解决方案,它仅将函数应用于成对的值,即1+62+7等。

所以我构建了一个函数,为我提供了所需的解决方案

myfunc <- function(z){lapply(a,calc,z)}

并将其应用于b

solution <- lapply(b,myfunc)

我们在这里看到与lapply(a,calc,b)或嵌套lapply(a,lapply,calc,b)的区别在于,它为我提供了自己列表中的所有值。那就是我想要的,或者至少它是一个为我提供正确结果而没有错误的函数。

现在,有没有一种更快/更简单的方法,因为我在这里做了一些尝试。而且我的函数要比calc大得多,它需要10分钟,但是也许我必须精简我的原始函数,并且这里没有更快的方法...

编辑:

在我的函数中,有这样的东西

calc <- function(x,y){
# ...
number <- x
example <- head(number,n=y)
# ...
}

其中向量作为y的输入不再起作用。使用lapply(a,lapply,calc,b)lapply(a,calc,b)时出现错误,

Error in head.default(number, n = y) : length(n) == 1L is not TRUE 

2 个答案:

答案 0 :(得分:1)

正如弗洛里安所说,outer()是一个选择。

outer(a, b, calc)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    7    8    9   10   11
# [2,]    8    9   10   11   12
# [3,]    9   10   11   12   13
# [4,]   10   11   12   13   14
# [5,]   11   12   13   14   15

但是,正如MichaelChirico所提到的那样,使用未向量化的功能将不起作用。在这种情况下,必须将其他东西一起砍掉。这些操作可能会或可能不会比您当前的解决方案更快。

所有组合(因此,calc(1, 6)calc(6, 1)都被执行,类似于outer()

计算数量:n 2

eg <- expand.grid(a, b)

m1 <- mapply(calc, eg[,1], eg[, 2])
matrix(m1, 5)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    7    8    9   10   11
# [2,]    8    9   10   11   12
# [3,]    9   10   11   12   13
# [4,]   10   11   12   13   14
# [5,]   11   12   13   14   15

只有唯一的组合(因此假设您的函数是对称的)

计算数量:(n 2 -n)/ 2

cn <- t(combn(1:length(a), 2))

m2 <- mapply(calc, a[cn[, 1]], b[cn[, 2]])
mat <- matrix(, length(a), length(a))
mat[upper.tri(mat)] <- m2
mat
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   NA    8    9   10   11
# [2,]   NA   NA   10   11   12
# [3,]   NA   NA   NA   12   13
# [4,]   NA   NA   NA   NA   14
# [5,]   NA   NA   NA   NA   NA

这第二个忽略对角线,但是添加这些值很容易,因为这是OP mapply()调用返回的结果。

diag(mat) <- mapply(calc, a, b)
mat
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    7    8    9   10   11
# [2,]   NA    9   10   11   12
# [3,]   NA   NA   11   12   13
# [4,]   NA   NA   NA   13   14
# [5,]   NA   NA   NA   NA   15

答案 1 :(得分:0)

这为我解决了这个问题,感谢@AkselA,在SIMPLIFY=FALSE函数中添加了mapply

eg <- expand.grid(a, b)

m1 <- mapply(calc, eg[,1], eg[, 2],SIMPLIFY=FALSE)

但是,此方法仅比我自己的OP中的解决方案快一点。