我有一个值向量 (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 ,而是 lengthintersect 。这是我对 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/

10-11 10:23