将函数应用于R中列表元素的所有成对组合

goc*_*lem 7 combinations r function list

我想将一个函数应用于列表元素的所有成对组合.每个元素都是具有相同长度的向量.我希望输出采用n x n矩阵格式,n即列表中的元素数量.

请考虑以下示例:

# Generating data
l <- list()
for(i in 1:5) l[[i]] <- sample(0:9, 5, T)

# Function to apply
foo <- function(x, y) 1 - sum(x * y) / sqrt(sum(x ^ 2) * sum(y ^ 2))

# Generating combinations
comb <- expand.grid(x = 1:5, y = 1:5)
Run Code Online (Sandbox Code Playgroud)

此循环有效,但速度很慢,输出未格式化为矩阵

# Applying function
out <- list()
for(i in 1:nrow(comb)) {
  out[[i]] <- foo(l[[comb[i, 'x']]], l[[comb[i, 'y']]])
}
Run Code Online (Sandbox Code Playgroud)

任何的想法?

cr1*_*ade 7

嵌套的sapply可以解决这个问题:

sapply(l, function(x) sapply(l, function(y) foo(x,y)))
Run Code Online (Sandbox Code Playgroud)

我对@A很感兴趣.韦伯的解决方案.以下是一些基准测试:

R> for(i in 1:50) l[[i]] <- sample(0:9, 5, T)
R> microbenchmark(sapply(l, function(x) sapply(l, function(y) foo(x,y))), outer(l,l,Vectorize(foo)), time=1000)
Unit: nanoseconds
                                                    expr     min        lq
 sapply(l, function(x) sapply(l, function(y) foo(x, y))) 7493739 8479127.0
                             outer(l, l, Vectorize(foo)) 6778098 8316362.5
                                                    time       5      48.5
      mean    median        uq      max neval
 1.042e+07 1.027e+07 1.155e+07 17982289   100
 1.030e+07 1.002e+07 1.187e+07 16076063   100
 1.672e+02 1.385e+02 1.875e+02      914   100

R> for(i in 1:500) l[[i]] <- sample(0:9, 5, T)
R> microbenchmark(sapply(l, function(x) sapply(l, function(y) foo(x,y))), outer(l,l,Vectorize(foo)), times=100)
Unit: milliseconds
                                                    expr   min    lq  mean
 sapply(l, function(x) sapply(l, function(y) foo(x, y))) 677.3 768.5 820.4
                             outer(l, l, Vectorize(foo)) 828.6 903.0 958.3
 median    uq  max neval
  815.9 842.7 1278   100
  930.7 960.5 1819   100
Run Code Online (Sandbox Code Playgroud)

因此对于较小的列表,外部解决方案要快一些,但对于较大的列表,嵌套的sapply解决方案似乎可能会更快一些.