这是我的意思的一个例子,这段代码输出正确的东西:
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循环来比较每一行的每一行?我有更大的矩阵和列表,所以这太慢了。
感谢您的帮助!
答案 0 :(得分: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
希望这是您正在寻找的效率提升。
答案 1 :(得分:0)
这是根据您的R高尔夫挑战的精神为您的问题提供的,一个紧凑的可能难以理解的解决方案:
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
转换为分数。 (它仍然是两个嵌套循环。)