2010-11-23 73 views
0

假设我有两个向量ba。后者的组成部分(a)几乎总是零,只有少数几个。具有R中另一个向量的分量函数的稀疏向量的分量乘积

如果我想计算的成分之积和一个逐个分量的功能(如EXP)的B,我可以做

a*exp(b) 

然而,对于的那些大部分零个组件,所述评价exp对b的相应组件将是一种浪费。

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

回答

2

要扩大迪文的回答,并把它的评论,只要保持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) 
} 

T母鸡用它

> all.equal(out, myFun(a, b)) 
[1] TRUE 

没有什么是比直接使用a * exp(b)更有效。 *exp()都是矢量化的,因此运行速度非常快,比迄今为止各种答案中使用的任何预订保留措施快得多。

您是否需要书记解决方案取决于您的功能(Q中示例中的exp())在计算方面的费用。尝试两种方法在一个小样本上,并评估时间(使用system.time()),看看是否值得额外的努力做子集跟踪0.

0

您可以通过为任何您认为是浪费的情况编制一个测试索引来实现这一目标。如果函数的时间比EXP昂贵的,它可能会有所作为:

a[ !b==0 ]*exp(b[!b==0]) 

也承认,有陷阱,以测试与数字模式的平等。你可能想看看zapsmall和all.equal作为替代品,这取决于真正的问题是什么。

> 3/10 == 0.1*3 
[1] FALSE 
+2

谢谢DWIN!但是[!b == 0] * exp(b [!b == 0])会给出* exp(b)的不同结果。 – Tim 2010-11-23 03:09:12

+0

-1它是'a',主要是0. – 2010-11-23 09:59:25

+0

是的。神经元串扰。应该是[!a == 0] * exp(b [!a == 0]),但是仍然不能提供完整的矢量。 – 2010-11-24 02:08:48

1

到迪文的建议类似:

> 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 
2

只是代替你的表达:

ifelse(a==0,0,a*exp(b)) 

我会感到惊讶,如果这做了性能改进,不过,由于R解释,运行ifelse的开销可能比浪费exp调用更差。