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

R: How to nicely divide all element of a vector by the sum of all the other element

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

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

一个简单的方法是使用 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

如您所见,这不仅是代码简单性的问题,也是性能问题。

试试这个代码:

v / (sum(v) - v)