首页 > 解决方案 > R矢量化操作

问题描述

我想获取数据帧的一列的每个元素(一个数字),通过将它乘以一个向量来获得一个向量,然后将它乘以数据帧中的每一行,将其转换为一个向量。

代码如下:

df = data.frame(matrix(rexp(1441*100, rate=.1), ncol=100))

out_vec <- c()
for (i in 1:nrow(df)) {


  out_vec[i]<- sum(df[i, 5:100] * (1 + abs(df$X1[i])/100) ^ -(0:95 / 12))

}

我怎样才能矢量化这段代码?我努力了

out_vec_alt <- rowSums(df[, 5:100] * (1 + abs(df$X1)/100) ^ -(0:95 / 12))

但它没有产生预期的结果:

all(out_vec_alt == out_vec) #FALSE

标签: r

解决方案


第二部分需要完成outer。您可以a^b以矢量化方式使用,但它不会将操作应用于 vs 的所有元素的第一个元素、avs 的所有元素的b第二个元素等,就像您在这种情况下想要的那样。它只会给。abc(a[1]^b[1], a[2]^b[2], ..., a[n]^b[n])

out_vec2 <- rowSums(df[5:100] * outer(1 + abs(df$X1)/100, -(0:95)/12, `^`))

all.equal(out_vec, out_vec2)
# [1] TRUE

显然这会更快,但我很惊讶地看到这个例子的速度超过了 200 倍(在中位时间)

loop <- function(){
  out_vec <- c()
  for (i in 1:nrow(df)) {
    out_vec[i]<- sum(df[i, 5:100] * (1 + abs(df$X1[i])/100) ^ -(0:95 / 12))
  }
  out_vec
}

vect <- function() rowSums(df[5:100] * outer(1 + abs(df$X1)/100, -(0:95)/12, `^`))

library(microbenchmark)
microbenchmark(loop(), vect(), times = 10)
# Unit: milliseconds
#    expr         min          lq        mean      median          uq        max neval
#  loop() 12065.34780 12756.12062 13095.97435 12892.87818 13460.56978 15030.0197    10
#  vect()    35.73011    41.36212    60.57327    54.40029    79.25182   104.0453    10

推荐阅读