稀疏向量的分量乘积,具有R中另一个向量的分量函数

时间:2010-11-23 00:51:13

标签: r

假设我有两个向量ba。后者的成分(a)几乎总是零,除了少数。

如果我想计算a的组件方式和b的组件方式(如exp),我可以做

a*exp(b)

然而,对于a的大多数零分量,对b的相应分量的exp的评估将是浪费。

我想知道在这样的情况下,是否可以在R中更有效地编程?或者没有必要改变。谢谢!

4 个答案:

答案 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