假设我们希望对向量x中的每一个元素使用函数f()。在很多情况下,我们可以简单地对x调用f()就能完成。这可以简化我们的代码,不仅如此,还能将代码运行效率显著提高到数百倍甚至更多。
►向量输入,向量输出
提高R代码执行速度的有效方法之一是向量化(vectorize),这意味着应用到向量上的函数实际上应用在其每一个元素上。
> u <- c( 5, 2, 8 )
> v <- c( 1, 2, 9 )
> u > v
[1] TRUE FALSE FALSE
> w <- function( x ) return( x + 1 )
> w( u )
[1] 6 3 9
在这里,>函数分别运用在u[1] 和v[1],得到结果TRUE,然后是u[2] 和 v[2],得到结果FALSE,以此类推。关键在于,如果一个函数使用了向量化的运算符,那么它也被向量化了,从而使速度提升成为可能。w()使用了向量化的运算符+,从而w()也是向量化的。正如你看到的,存在无数个向量化的函数,因为用简单的向量化函数可以构建更复杂的函数。
> y <- c( 12, 5, 13 )
> y + 4
[1] 16 9 17
> '+' ( y, 4 )
[1] 16 9 17
> f <- function( x, c ) return ( (x+c)^2 )> f( 1:3, 0 )
[1] 1 4 9
> f( 1:3, 0 )
[1] 1 4 9
> f( 1:3, 1:3 )
[1] 4 16 36
在这里定义的f(),我们希望c是一个标量,但实际上它当然是一个长度为1的向量。即使我们调用f()时给c指定的是单个数值,在f()计算x+c时,它也会通过循环补齐的方式延展为一个向量。
►向量输入,矩阵输出
到目前为止,我们涉及的向量化函数应用于标量时返回值也是标量。对单个数值调用sqrt()函数得到的结果也是单个数值。
> z12 <- function(z) return ( c( z, z^2 ) )
> x <- 1 : 8
> z12( x )
[1] 1 2 3 4 5 6 7 8 1 4 9 16 25 36 49 64
> matrix( z12(x), ncol=2 )
[,1] [,2]
[1,] 1 1
[2,] 2 4
[3,] 3 9
[4,] 4 16
[5,] 5 25
[6,] 6 36
[7,] 7 49
[8,] 8 64
> z12 <- function(z) return ( c( z, z^2 ) )
> sapply( 1:8, z12 )
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 2 3 4 5 6 7 8
[2,] 1 4 9 16 25 36 49 64
注:可以用sapply()(它是simplify apply的缩写)来简化这一切。调用sapply(x,f)即可对x的每一个元素使用函数f(),并将结果转化为矩阵。