簡體   English   中英

R中的非向量列表的external()等效項

[英]outer() equivalent for non-vector lists in R

我了解在R中external()是如何工作的:

> outer(c(1,2,4),c(8,16,32), "*")

     [,1] [,2] [,3]
[1,]    8   16   32
[2,]   16   32   64
[3,]   32   64  128

它基本上采用2個向量,找到這些向量的叉積,然后將函數應用於叉積中的每一對。

但是,我沒有兩個向量。 我有兩個矩陣列表:

M = list();

M[[1]] = matrix(...)
M[[2]] = matrix(...)
M[[3]] = matrix(...)

我想對矩陣列表進行操作。 我想要做:

outer(M, M, "*")

在這種情況下,我要獲取我擁有的每種矩陣組合的點積。

實際上,我正在嘗試生成內核矩陣(並且我已經編寫了內核函數),所以我想這樣做:

outer(M, M, kernelFunction)

其中, kernelFunction計算兩個矩陣之間的距離。

問題在於,outer()僅接受“向量”參數,而不是“列表”等。是否有一個函數對非向量實體而言等效於outer()?

或者,我可以使用for循環來執行此操作:

M = list() # Each element in M is a matrix

for (i in 1:numElements)
{
   for (j in 1:numElements)
   {
      k = kernelFunction(M[[i]], M[[j]])
      kernelMatrix[i,j] = k;
   }
} 

但我試圖避免這種情況,而推薦使用R構造(可能會更有效)。 (是的,我知道我可以修改for循環以計算對角矩陣並節省50%的計算。但這不是我要優化的代碼!)

這可能嗎? 有什么想法/建議嗎?

外部函數確實在列表上起作用,但是您提供的函數會重復獲取兩個輸入向量,以便它們包含所有可能的組合...

至於哪一個更快,將external與vapply組合起來比我的機器上的double for循環快3倍。 如果實際的內核功能確實“起作用”,則循環速度的差異可能並不那么重要。

f1 <- function(a,b, fun) {
  outer(a, b, function(x,y) vapply(seq_along(x), function(i) fun(x[[i]], y[[i]]), numeric(1)))
}

f2 <- function(a,b, fun) {
    kernelMatrix <- matrix(0L, length(a), length(b))
    for (i in seq_along(a))
    {
       for (j in seq_along(b))
       {
          kernelMatrix[i,j] = fun(a[[i]], b[[j]])
       }
    }
    kernelMatrix
}

n <- 300
m <- 2
a <- lapply(1:n, function(x) matrix(runif(m*m),m))
b <- lapply(1:n, function(x) matrix(runif(m*m),m))
kernelFunction <- function(x,y) 0 # dummy, so we only measure the loop overhead

> system.time( r1 <- f1(a,b, kernelFunction) )
   user  system elapsed 
   0.08    0.00    0.07 
> system.time( r2 <- f2(a,b, kernelFunction) )
   user  system elapsed 
   0.23    0.00    0.23 
> identical(r1, r2)
[1] TRUE

只需使用for循環。 無論如何,任何內置函數都將退化為該函數,除非您仔細構建一個泛化到列表之外的函數,否則您將失去表達的清晰度。

您可以做的最大改進就是預分配矩陣:

M <- list()
length(M) <- numElements ^ 2
dim(M) <- c(numElements, numElements)

PS。 列表是一個向量。

盡管這是一個古老的問題,但這是另一個解決方案,它更多地體現了外部功能的精神。 這個想法是沿着list1和list2的索引應用外部的:

cor2 <- Vectorize(function(x,y) {
   vec1 <- list1[[x]]
   vec2 <- list2[[y]]
   cor(vec1,vec2,method="spearman")
})
outer(1:length(list1), 1:length(list2), cor2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM