假设我有两个向量b
和a
。后者的成分(a
)几乎总是零,除了少数。
如果我想计算a的组件方式和b的组件方式(如exp),我可以做
a*exp(b)
然而,对于a的大多数零分量,对b的相应分量的exp的评估将是浪费。
我想知道在这样的情况下,是否可以在R中更有效地编程?或者没有必要改变。谢谢!
答案 0 :(得分:2)
只需用以下代码替换表达式:
ifelse(a==0,0,a*exp(b))
如果这会带来性能提升,我会感到惊讶,但是,由于R被解释,运行ifelse
的开销可能比浪费exp
调用更糟糕。
答案 1 :(得分:2)
要扩展DWin的答案以及对它的评论,只需跟踪0
并添加回原点答案:
## Dummy data
set.seed(1)
a <- sample(0:10, 100, replace = TRUE)
b <- runif(100)
## something to hold results
out <- numeric(length(a))
## the computations you *want* to do
want <- !a==0
## fill in the wanted answers
out[want] <- a[want] * exp(b[want])
这给出了正确的结果:
> all.equal(out, a * exp(b))
[1] TRUE
如果您愿意,可以将其包装成一个函数:
myFun <- function(a, b) {
out <- numeric(length(a))
want <- !a==0
out[want] <- a[want] * exp(b[want])
return(out)
}
然后使用它
> all.equal(out, myFun(a, b))
[1] TRUE
但这一点都不比直接使用a * exp(b)
更有效。 *
和exp()
都是矢量化的,因此运行速度非常快,比目前各种答案中使用的任何预订措施都要快得多。
您是否需要簿记解决方案取决于您的功能(Q中示例中为exp()
)的计算成本。在小样本上尝试两种方法并评估时间(使用system.time()
),看看是否值得花费额外的努力来进行子集跟踪0。
答案 2 :(得分:1)
类似于DWin的建议:
> n <- 1e5
> nonzero <- .01
> b <- rnorm(n)
> a <- rep(0, n)
> a[1:(n*nonzero)] <- rnorm(n*nonzero)
>
> system.time(replicate(100, {
+ c <- a*exp(b)
+ }))
user system elapsed
1.19 0.05 1.23
> system.time(replicate(100, {
+ zero <- a < .Machine$double.eps
+ c <- a
+ c[!zero] <- a[!zero]*exp(b[!zero])
+ }))
user system elapsed
0.42 0.08 0.50
答案 3 :(得分:0)
您可以通过将两个向量编入索引来完成此操作,并测试您认为浪费的任何情况。如果函数比exp更耗费时间,那么它可能会有所不同:
a[ !b==0 ]*exp( b[!b==0] )
还要认识到有数据模式测试相等性的陷阱。您可能希望将zapsmall和all.equal视为替代方案,具体取决于真正的问题。
> 3/10 == 0.1*3
[1] FALSE