假设我有两个向量
a <- c(1,2,3,4,5)
b <- c(6,7,8,9,10)
和一个功能
calc <- function(x,y){x + y)
我想将此功能应用于a
中每个值的b
中的第一个值。假设在我的情况下,calc
仅允许来自a
和b
的单个值作为输入,因此lapply(a,calc,b)
将不起作用,因为length(b)不是1,则(给我一个错误)。
mapply
也不给我想要的解决方案,它仅将函数应用于成对的值,即1+6
,2+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
答案 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中的解决方案快一点。