2014-06-18 48 views
2

這裏是我的意思的例子,該代碼輸出正確的事:如何有效地將矩陣的每一行與R中列表的每一部分進行比較?

list1 = list(c(1,2,3,4), c(5,6,7), c(8,9), c(10, 11)) 
matrix1 = rbind(c(1,2), c(1,5), c(8, 10)) 

compare <- function(list.t, matrix.t) { 
    pairs <- 0 
    for (i in 1:nrow(matrix.t)) { 
     for (j in 1:length(list.t)) { 
       if (length(intersect(matrix.t[i,], list.t[[j]])) == 2) { 
         pairs <- pairs + 1 
       } 
     } 
    } 
    return(pairs/nrow(matrix.t)) 
} 

compare(list1, matrix1) 
# = 0.33333 

我希望是有道理的。我試圖取一個nx2矩陣,並查看矩陣的每一行的兩個元素是否也在列表的每一部分中找到。所以,在上面的例子中,矩陣的第一行是(1,2),這個對在列表的第一部分找到。 (1,5)或(8,10)對在列表的任何部分都找不到。所以這就是爲什麼我輸出0.3333(1/3)。

我想知道是否有人知道不使用兩個for-loops來比較每一行到每個部分的方式?我有更大的矩陣和列表,所以這太慢了。

謝謝你的幫助!

回答

1

這不會工作嗎?您可以在列表上調用sapply,並同時與矩陣的所有行進行比較。

> list1 = list(c(1,2,3,4), c(5,6,7), c(8,9), c(10, 11)) 
> matrix1 = rbind(c(1,2), c(1,5), c(8, 10)) 

> s <- sapply(seq_along(list1), function(i){ 
     length(intersect(list1[[i]], matrix1)) == 2 
    }) 
> sum(s)/nrow(matrix1) 
# [1] 0.3333333 

如果我們調用函數f1(),這sapply版本相同的功能f2()的,我們得到的速度以下區別。

> library(microbenchmark) 
> microbenchmark(f1(), f2()) 
# Unit: microseconds 
# expr  min  lq median  uq  max neval 
# f1() 245.017 261.2240 268.843 281.7350 1265.706 100 
# f2() 113.727 117.7045 125.478 135.6945 268.310 100 

希望這是您尋找效率的增加。

+0

更大程度的矢量化。我認爲也更容易理解。 –

0

這是獻過你的[R高爾夫挑戰的精神,爲您的問題,一個緊湊的BU可能高深莫測的解決方案:

mean(apply(matrix1, 1, 
      function(x) any({lapply(list1, function(z) {all(x %in% z) })})) 
    ) 

[1] 0.3333333 

內lapply測試list1特定元素是否具有無論是在項目的從元素matrix1開始的兩元素向量傳遞。然後any函數測試4個元素中的任何元素是否滿足特定行的挑戰。中間邏輯矢量c(TRUE,FALSE,FALSE)mean轉換成分數。 (它仍然真的是兩個嵌套循環。)

相關問題