更新:
当然 mape 可以矢量化:
mapeVec <- function(y, yhat)
colMeans(abs((y-yhat)/y))
f3 <- function() { mapeVec(y, yp) }
Unit: milliseconds
expr min lq mean median uq max neval cld
f1() 33.677431 34.121107 35.494355 34.441823 35.078125 46.16782 100 b
f2() 33.558224 33.970123 35.609414 34.239525 34.881354 49.99195 100 b
f3() 8.344952 8.525146 9.218695 8.568763 8.709681 17.82791 100 a
identical(f1(), f3()) # TRUE
旧部分:
sapply 与序列 seq(nrow(y)) 应该可以解决问题:
mape <- function(y, yhat)
mean(abs((y - yhat)/y))
y <- matrix(c(11, 12, 12, 12, 14, 16, 23, 21, 28), nrow = 3, ncol = 3)
yp = matrix(c(12, 13, 14, 12, 15, 17, 24, 22, 28), nrow = 3, ncol = 3)
sapply(seq(nrow(y)), function(id) { mape(y[,id], yp[,id]) })
微基准测试:
library(microbenchmark)
mape <- function(y, yhat)
mean(abs((y - yhat)/y))
y <- matrix(rnorm(1000000), nrow = 1000, ncol = 1000)
yp = matrix(rnorm(1000000), nrow = 1000, ncol = 1000)
f1 <- function() { sapply(seq(nrow(y)), function(id) { mape(y[,id], yp[,id]) }) }
f2 <- function() {
a <- vector(mode = "numeric", length = nrow(y))
for(id in seq(nrow(y))) {
a[id] <- mape(y[,id], yp[,id])
}
a
}
microbenchmark(
f1(),
f2()
)
结果:
Unit: milliseconds
expr min lq mean median uq max neval cld
f1() 33.28310 34.15209 36.57389 35.42845 36.20803 48.11936 100 a
f2() 34.14755 34.78859 37.65782 36.33395 37.06874 64.10664 100 a
个人评论:
f1(sapply() 方法)看起来更加紧凑和“干净”。