【问题标题】:Speeding up function that uses which within a sapply call in R在 R 的 sapply 调用中使用 which 的加速函数
【发布时间】:2012-10-19 20:42:19
【问题描述】:

我有两个向量 eg。我想知道e 中的每个元素在g 中较小的元素的百分比。在 R 中实现这一点的一种方法是:

set.seed(21)
e <- rnorm(1e4)
g <- rnorm(1e4)
mf <- function(p,v) {100*length(which(v<=p))/length(v)}
mf.out <- sapply(X=e, FUN=mf, v=g)

对于较大的eg,这需要很长时间才能运行。如何更改或调整此代码以使其运行得更快?

注意:上面的 mf 函数是基于 dismo 包中 mess 函数的代码。

【问题讨论】:

  • 您可以将 mf 更改为 mf &lt;- function(p,v){100*mean(v&lt;=p)},但我不确定这会有多大帮助。
  • 谢谢 Dason,但这似乎需要更多时间
  • vapply 而不是 sapply 可能会有所帮助。
  • @Paulo 真的吗?在我的系统上花费的时间更少......
  • @Dason,不,它没有,你是对的,你的解决方案需要更少的时间。我昨天测试的时候一定是搞错了,抱歉。

标签: r sapply


【解决方案1】:

之所以这么慢,是因为您正在调用您的函数length(e) 次。它对小向量并没有太大的区别,但是 R 函数调用的开销确实开始与更大的向量相加。

通常,您需要将其移至编译代码,但幸运的是您可以使用findInterval

set.seed(21)
e <- rnorm(1e4)
g <- rnorm(1e4)
O <- findInterval(e,sort(g))/length(g)

# Now for some timings:
f <- function(p,v) mean(v<=p)
system.time(o <- sapply(e, f, g))
#   user  system elapsed 
#   0.95    0.03    0.98
system.time(O <- findInterval(e,sort(g))/length(g))
#   user  system elapsed 
#      0       0       0 
identical(o,O)  # may be FALSE
all.equal(o,O)  # should be TRUE

# How fast is this on large vectors?
set.seed(21)
e <- rnorm(1e7)
g <- rnorm(1e7)
system.time(O <- findInterval(e,sort(g))/length(g))
#   user  system elapsed 
#  22.08    0.08   22.31

【讨论】:

  • 谢谢@Joshua,很好的回答。速度提升是惊人的。一个小的修正来获得与原始函数相同的输出:findInterval(e,sort(g))/length(g)
猜你喜欢
  • 2021-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多