我有一个值向量 (x)。
我想确定它与位于列表 (y) 中的每个集合的重叠长度 - 但不运行循环或 lapply。是否可以?
我真的对加速执行很感兴趣。
非常感谢你!
下面是一个使用循环实现的示例:
x <- c(1:5)
y <- list(1:5, 2:6, 3:7, 4:8, 5:9, 6:10)
overlaps <- rep(0, length(y))
for (i in seq(length(y))) { #i=1
# overlaps[i] <- length(intersect(x, y[[i]])) # it is slower than %in%
overlaps[i] <- sum(x %in% y[[i]])
}
overlaps
以下是对以下回复中建议的一些方法的比较。如您所见,循环仍然是最快的 - 但我很想找到更快的东西:
# Function with the loop:
myloop <- function(x, y) {
overlaps <- rep(0, length(y))
for (i in seq(length(y))) overlaps[i] <- sum(x %in% y[[i]])
overlaps
}
# Function with sapply:
mysapply <- function(x, y) sapply(y, function(e) sum(e %in% x))
# Function with map_dbl:
library(purrr)
mymap <- function(x, y) {
map_dbl(y, ~sum(. %in% x))
}
library(microbenchmark)
microbenchmark(myloop(x, y), mysapply(x, y), mymap(x, y), times = 30000)
# Unit: microseconds
# expr min lq mean median uq max neval
# myloop(x, y) 17.2 19.4 26.64801 21.2 22.6 9348.6 30000
# mysapply(x, y) 27.1 29.5 39.19692 31.0 32.9 20176.2 30000
# mymap(x, y) 59.8 64.1 88.40618 66.0 70.5 114776.7 30000
最佳答案
使用 sapply 使代码紧凑。
即使 sapply
并没有带来太多的性能优势,但与 for 循环相比,至少代码要紧凑得多。这是 sapply
等效于您的代码:
x <- c(1:5)
y <- list(1:5, 2:6, 3:7, 4:8, 5:9, 6:10)
res <- sapply(y, function(e) length(intersect(e, x)))
> res
[1] 5 4 3 2 1 0
性能提升
正如@StupidWolf 正确指出的那样,减慢执行速度的不是
sapply
,而是 length
和 intersect
。这是我对 100.000
执行的测试:B <- 100000
system.time(replicate(B, sapply(y, function(e) length(intersect(e, x)))))
user system elapsed
9.79 0.01 9.79
system.time(replicate(B, sapply(y, function(e) sum(e %in% x))))
user system elapsed
2 0 2
#Using microbenchmark for preciser results:
library(microbenchmark)
microbenchmark(expr1 = sapply(y, function(e) length(intersect(e, x))), times = B)
expr min lq mean median uq max neval
expr1 81.4 84.9 91.87689 86.5 88.2 7368.7 1e+05
microbenchmark(expr2 = sapply(y, function(e) sum(e %in% x)), times = B)
expr min lq mean median uq max neval
expr2 15.4 16.1 17.68144 16.4 17 7567.9 1e+05
正如我们所看到的,第二种方法是迄今为止性能的赢家。
希望这可以帮助。
关于R 将一组值与多组值进行比较,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59686200/