如何使用R自动化两个矩阵的每列之间的操作?

如何使用R自动化两个矩阵的每列之间的操作?,r,for-loop,matrix,lapply,sapply,R,For Loop,Matrix,Lapply,Sapply,我有为MAPE编写的通用函数(平均绝对百分比误差) 并预测为 yp = matrix(c(12, 13, 14, 12, 15, 17, 24, 22, 28),byrow=TRUE,ncol=3) 这可以手动为每个列执行,如mape(y[,1],yp[,1]) 我如何使用R自动化在大维度矩阵的每列之间执行操作的过程(也包括任何其他操作-不仅仅是MAPE)?使用apply/sapply可以避免FOR循环吗?更新: 当然,mape可以矢量化: mapeVec <- function(y,

我有为MAPE编写的通用函数(平均绝对百分比误差)

并预测为

yp = matrix(c(12, 13, 14, 12, 15, 17, 24, 22, 28),byrow=TRUE,ncol=3)
这可以手动为每个列执行,如
mape(y[,1],yp[,1])

我如何使用R自动化在大维度矩阵的每列之间执行操作的过程(也包括任何其他操作-不仅仅是MAPE)?使用apply/sapply可以避免FOR循环吗?

更新: 当然,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
微基准: 个人评论:
f1
sapply()
approach)看起来更加紧凑和“干净”

更新: 当然,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
微基准: 个人评论:
f1
sapply()
approach)看起来更加紧凑和“干净”

如果另一种选择是使用
apply
sapply
,您可以安全地将
用于
循环,基本上没有任何负面影响。用
apply
替换循环不会加快速度。如果替代方法是使用
apply
sapply
,则可以安全地使用
for
循环,基本上没有任何负面影响。用
apply
替换循环不会加快速度。可以用
seq(nrow(y))
替换
seq(1:dim(y)[1])
。它没有改变任何东西,只是使长度从何而来变得更加明显。无法抗拒:
microbenchmark(seq(1:dim(y)[1]),seq(nrow(y)),times=1000)
给出了
10.82
vs
9.88
的意思和
9.87
vs
8.69
中间值。这是因为你使用了
seq(1:dim(y)[1])
,也就是说,你基本上是两次排序。如果改用
seq(dim(y)[1])
则得到完全相同的结果。如果您试图优化速度,请改用
seq_len
。您可以将
seq(1:dim(y)[1])
替换为
seq(nrow(y))
。它没有改变任何东西,只是使长度从何而来变得更加明显。无法抗拒:
microbenchmark(seq(1:dim(y)[1]),seq(nrow(y)),times=1000)
给出了
10.82
vs
9.88
的意思和
9.87
vs
8.69
中间值。这是因为你使用了
seq(1:dim(y)[1])
,也就是说,你基本上是两次排序。如果改用
seq(dim(y)[1])
则得到完全相同的结果。如果您试图优化速度,请改用
seq_len
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
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