为了账号安全,请及时绑定邮箱和手机立即绑定

“*应用”家庭真的没有矢量化吗?

“*应用”家庭真的没有矢量化吗?

慕侠2389804 2019-06-28 09:53:47
“*应用”家庭真的没有矢量化吗?所以我们习惯于对每一个R的新用户说apply不是矢量化的,看看帕特里克·伯恩斯r地狱第4圈“它说(我引述):一个常见的反射是在应用程序家族中使用一个函数。这不是 矢量化,是循环隐藏。..Apply函数的定义中有一个for循环。lApplication函数掩埋循环,但执行时间往往与显式for循环大致相等。实际上,快速查看一下apply源代码显示了循环:grep("for", capture.output(getAnywhere("apply")), value = TRUE)## [1] "        for (i in 1L:d2) {"  "    else for (i in 1L:d2) {"好的,但是看看lapply或vapply实际上展示了一幅完全不同的画面:lapply## function (X, FUN, ...) ## {##     FUN <- match.fun(FUN)##     if (!is.vector(X) || is.object(X)) ##        X <- as.list(X)##     .Internal(lapply(X, FUN))## }## <bytecode: 0x000000000284b618>## <environment: namespace:base>所以很明显没有Rfor循环隐藏在那里,而是调用内部C编写函数。快速浏览兔子 孔洞显示了几乎相同的图片另外,让我们把colMeans函数,它从未被指责没有被传送。colMeans# function (x, na.rm = FALSE, dims = 1L) # {#   if (is.data.frame(x)) #     x <- as.matrix(x)#   if (!is.array(x) || length(dn <- dim(x)) < 2L) #     stop("'x' must be an array of at least two dimensions")#   if (dims < 1L || dims > length(dn) - 1L) #     stop("invalid 'dims'")#   n <- prod(dn[1L:dims])#   dn <- dn[-(1L:dims)]#   z <- if (is.complex(x)) #     .Internal(colMeans(Re(x), n, prod(dn), na.rm)) + (0+1i) * #     .Internal(colMeans(Im(x), n, prod(dn), na.rm))#   else .Internal(colMeans(x, n, prod(dn), na.rm))#   if (length(dn) > 1L) {#     dim(z) <- dn#     dimnames(z) <- dimnames(x)[-(1L:dims)]#   }#   else names(z) <- dimnames(x)[[dims + 1]]#   z# }# <bytecode: 0x0000000008f89d20>#   <environment: namespace:base>哈?它也只是打电话.Internal(colMeans(...我们也可以在兔洞..所以这和.Internal(lapply(..?事实上,一个快速的基准测试显示sapply表现不逊于colMeans比for用于大数据集的循环。m <- as.data.frame(matrix(1:1e7, ncol = 1e5))system.time(colMeans(m))# user  system elapsed # 1.69    0.03    1.73 system.time(sapply(m, mean))# user  system elapsed # 1.50    0.03    1.60 system.time(apply(m, 2, mean))# user  system elapsed # 3.84    0.03    3.90 system.time(for(i in 1:ncol(m)) mean(m[, i]))# user  system elapsed # 13.78    0.01   13.93换句话说,这么说对吗?lapply和vapply 实际上是矢量化的(与apply这是for循环,它也调用lapply帕特里克·伯恩斯到底想说什么?
查看完整描述

3 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

对我来说,矢量化主要是使代码更易于编写和理解。

矢量化函数的目标是消除与for循环相关的簿记。例如,而不是:

means <- numeric(length(mtcars))for (i in seq_along(mtcars)) {
  means[i] <- mean(mtcars[[i]])}sds <- numeric(length(mtcars))for (i in seq_along(mtcars)) {
  sds[i] <- sd(mtcars[[i]])}

你可以写:

means <- vapply(mtcars, mean, numeric(1))sds   <- vapply(mtcars, sd, numeric(1))

这样就可以更容易地看到什么是相同的(输入数据)和什么是不同的(您正在应用的函数)。

矢量化的另一个优点是,for循环通常是用C编写的,而不是用R编写的,这有很大的性能优势,但我不认为它是矢量化的关键属性。矢量化从根本上讲是为了拯救你的大脑,而不是拯救计算机工作。


查看完整回答
反对 回复 2019-06-28
  • 3 回答
  • 0 关注
  • 476 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信