作为标题,我想知道如何在R中定义矢量化函数。
答案 0 :(得分:32)
R级别的循环不是矢量化。 R循环将为向量的每个元素调用相同的R代码,这将是低效的。矢量化函数通常指的是采用向量并以有效方式对整个向量进行操作的函数。最终,这将涉及一些for循环,但由于该循环是在诸如C的低级语言中执行的,因此它可以非常高效并且针对特定任务进行定制。
考虑这个愚蠢的函数来成对地添加两个向量的元素
sillyplus <- function(x, y) {
out <- numeric(length = length(x))
for(i in seq_along(x)) {
out[i] <- x[i] + y[i]
}
out
}
它给出了正确的结果
R> sillyplus(1:10, 1:10)
[1] 2 4 6 8 10 12 14 16 18 20
并且它在某种意义上被矢量化,它可以同时对整个矢量进行操作,但在上面描述的意义上它不是矢量化,因为它非常低效。 +
在R中的C级进行矢量化,因此我们实际上只需要1:10 + 1:10
,而不是R中的显式循环。
编写矢量化函数的常用方法是使用已经矢量化的现有R函数。如果你想从头开始,你想要用函数做的事情不是作为R中的矢量化函数存在(奇数,但可能),那么你需要弄清楚你的手并写下函数的内容C并在R中准备一个小包装器,用您希望它处理的数据向量调用您编写的C函数。有些方法可以使用像Vectorize()
这样的函数伪造没有矢量化的R函数的矢量化。
C不是唯一的选择,FORTRAN是C ++的可能性,感谢Dirk Eddelbuettel&amp; Romain Francois,后者使用 rcpp 包更容易做到。
答案 1 :(得分:9)
向量化函数将返回与其参数之一相同长度的向量。通常,人们可以通过使用内置函数的组合来实现这样的功能,例如“+”,cos
或exp
也可以进行矢量化。
vecexpcos <- function(x) exp(cos(x))
vecexpcos( (1:10)*pi )
> vecexpcos( (1:10)*pi )
# [1] 0.3678794 2.7182818 0.3678794 2.7182818 0.3678794 2.7182818 0.3678794 2.7182818 0.3678794 2.7182818
如果您需要使用sum
之类的非向量化函数,则可能需要调用mapply
或Vectorize
才能获得所需的行为。
答案 2 :(得分:0)
聚会晚了,但我认为这个问题仍然非常相关,并且最近有一些新方法很受欢迎。所以还有另一种在 R 中向量化函数的方法,使用 tidyverse
方法。
首先定义一些数据:
x <- c(1,2,3)
y <- c(1,2,4)
现在,假设我们想对这两个向量执行一些元素方式计算,使得 f(x,y)
。
例如,计算 x 和 y 的每个(对)元素的总和应该得到:2,4,7。
让我们使用 map2_dbl
中的 purrr
(来自 tidyverse 生态系统的包):
x <- c(1,2,3)
y <- c(1,2,4)
library(tidyverse)
map2_dbl(.x = x,
.y = y,
.f = sum)
#> [1] 2 4 7
可以看出,从 x 和 y 的每对元素计算总和的意义上,结果是向量化的。
总而言之,至少在某些情况下,使用 map()
及其变体是向量化函数的便捷方式。