R:如何很好地将矢量的所有元素除以所有其他元素的总和

时间:2015-10-23 13:27:00

标签: r for-loop apply lapply

我想创建一个函数,用每个元素的值除以所有其他元素的总和来替换向量的所有元素。我创建了这个函数,但我确信有更好更简单的方法来编写它:

v1=runif(10)
v2=c()
l=1:length(v1)
for(i in l){
    v2=c(v2,(v1[i]/sum(v1[l[l!=i]])))
}
v1=v2

2 个答案:

答案 0 :(得分:3)

试试这段代码:

v / (sum(v) - v)

答案 1 :(得分:1)

执行此操作的一种简单方法是使用vapply函数(另请参阅this thread):

myfun <- function(x) {
   vapply(seq_along(x), function(i) x[i] / sum(x[-i]), numeric(1))
}

myfun(1:10)
## [1] 0.01851852 0.03773585 0.05769231 0.07843137 0.10000000 0.12244898 0.14583333 0.17021277 0.19565217 0.22222222

for - 循环在R中通常很慢且笨拙,所以如果没有必要,最好避免。但是,即使您出于某些原因需要for - 循环,也可以进行小的改进:

forfun <- function(x) {
  out <- numeric() # you know in advance that it will be a numeric vector
  for(i in seq_along(x)) {
    # R treats everything as a vector, so you can assign values
    # to every i-th element of any vector (even the empty one)
    # while concatenating c(x, x[i] / sum(x[-i])) slows things
    out[i] <- x[i] / sum(x[-i])
  }
  out
}

现在,让我们比较效果(forfun1是您的初始代码,forfun2是带有for的代码 - 循环但经过更正,myfunvapply版本):

> benchmark(forfun1(runif(1000)), forfun2(runif(1000)), myfun(runif(1000)))
                  test replications elapsed relative user.self sys.self user.child sys.child
1 forfun1(runif(1000))          100    1.46    1.207      1.47        0         NA        NA
2 forfun2(runif(1000))          100    1.30    1.074      1.29        0         NA        NA
3   myfun(runif(1000))          100    1.21    1.000      1.20        0         NA        NA

正如您所看到的,不仅是代码的简单性,还有它的性能。