如何在R中定义矢量化函数

zjf*_*fdu 34 r

作为标题,我想知道如何在R中定义矢量化函数.

  • 它只是在函数中使用循环吗?
  • 这种方法有效吗?
  • 什么是最佳做法?

Rei*_*son 34

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
}
Run Code Online (Sandbox Code Playgroud)

它给出了正确的结果

R> sillyplus(1:10, 1:10)
 [1]  2  4  6  8 10 12 14 16 18 20
Run Code Online (Sandbox Code Playgroud)

并且它在某种意义上被矢量化,它可以同时对整个矢量进行操作,但是在我上面描述的意义上它没有被矢量化,因为它非常低效.+在R中的C级向量化,所以我们真的只需要1:10 + 1:10,而不是R中的显式循环.

编写矢量化函数的常用方法是使用已经向量化的现有R函数.如果你想从头开始,你想要用函数做的事情不是作为R中的矢量化函数存在(奇数,但可能),那么你需要弄清楚你的手并写下函数的内容C并在R中准备一个小包装器,用您希望它处理的数据向量调用您编写的C函数.有一些函数Vectorize()可以伪造矢量化,用于没有矢量化的R函数.

C不是唯一的选择,FORTRAN是C++的可能性,感谢Dirk Eddelbuettel和Romain Francois,后者使用rcpp包更容易做到.


42-*_*42- 11

向量化函数将返回与其参数之一相同长度的向量.通常,人们可以通过使用内置函数(如"+")的组合来获得这样的功能,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
Run Code Online (Sandbox Code Playgroud)

如果您需要使用非向量化函数sum,则可能需要调用mapply或Vectorize以获得所需的行为.


Vis*_*rma 5

该函数的目的Vectorize是增强普通函数考虑 R 中向量化概念的能力。

例如,考虑下面的减法函数:

difftemp <- function(x){
    if(x > 10)
        return(x*10 - x)
    else
        return(x)
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的函数,如果输入值大于 10,则返回小于输入值 10 倍的值。如果输入值小于 10,则它将简单地返回相同的值。

> difftemp(100)
# [1] 900
Run Code Online (Sandbox Code Playgroud)

但是,当您对向量应用相同的函数时,它将失败。

> difftemp(mtcars$mpg)
# Error in if (x > 10) return(x * 10 - x) else return(x) : 
#  the condition has length > 1
Run Code Online (Sandbox Code Playgroud)

这是因为该函数不支持矢量化。为了使这个函数向量化,我们需要使用VectorizeR中的函数。例如:

# Vectorize difftemp function
> difftemp_v <- Vectorize(difftemp)

> difftemp_v(mtcars$mpg)
# [1] 189.0 189.0 205.2 192.6 168.3 162.9 128.7 219.6 205.2 172.8 160.2 147.6 155.7 136.8  93.6  93.6 132.3 291.6 273.6 305.1 193.5 139.5
# [23] 136.8 119.7 172.8 245.7 234.0 273.6 142.2 177.3 135.0 192.6
Run Code Online (Sandbox Code Playgroud)

继续编码!