系统自学R的第九天#参考书籍《R语言编程艺术》

似乎是有连续两天没搞了,真是罪过!

向量化运算符

假设我们希望对向量X中的每一个元素使用函数f()。
在很多情况下,我们可以简单地对x调用f()就能完成。
这可以简化我们的代码,不仅如此,还能将代码运行效率显著提高到数百倍甚至更多。
提高R代码执行速度的有效方法之一是向量化(vectorize),这意味着应用到向量上的承数实际上应用在其每一个元素上。

  • 向量输入,向量输出

之前在本章你已经看到向量化运算的一些例子,即**+运算符。另一个例子是>*。

> u<- c(5,2,8)
> V<-c(1,3,9)
> u>V
[1]  TRUE FALSE FALSE

在这里,>函数分别运用在u[1]和v[1],得到结果TRUE,然后是u[2]和v[2],得到结果 FALSE,以此类推。
关键在于,如果一个函数使用了向量化的运算符,那么它也被向量化了,从而使速度提升成为可能。下面有一个例子:

> w<-function(x)return(x+1)
> w(u)
[1] 6 3 9

在这里,w()使用了向量化的运算符+,从而w()也是向量化的。正如你看到的,存在无数个向量化的函数,因为用简单的向量化函数可以构建更复杂的函数。
注意,甚至**超越函数–(平方根、对数、三角函数等)**也是向量化的。

> sqrt(1:9)#1到9开平方根
[1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490
[7] 2.645751 2.828427 3.000000

这也适用于其他许多内置的R函数。例如,让我们对向量y应用round()函数,其作用是四舍五人到最近整数:

> y<- c(1.2,3.9,0.4)
> z<- round(y)
> z
[1] 1 4 0

上例的关键在于,round()函数能应用到向量y中的每一个元素上。
记住,标量实际上是一元向量,所以通常情况下对单个数值使用round()函数,只是一种特殊情形。

> round(1.2)
[1] 1

在这里,我们使用内置的函数round(),但用自己编写的函数同样可以做到这点。
正如前面提到过的,诸如+这样的运算符实际上也是函数。例如,考虑下面的代码:

> y<- c(12,5,13)
> y+4
[1] 16  9 17

上例中三元向量的每个元素都加上了4,原因在于+实际上也是函数!下面这样写就看得明显了:

> '+'(y,4)
[1] 16  9 17

同时也要注意,循环补齐在这里起了关键作用,4被循环补齐为(4,4,4)
我们知道R有没有标量,那么我们考察一下那些看上去有标量参数的向量化函数。

> f<-function(x,c) return((x+c)^2)
> f(1:3,0)
[1] 1 4 9
> f(1:3,1)
[1]  4  9 16

在这里定义的f(),我们希望c是一个标量,但实际上它当然是一个长 1 度为1的向量。
后续的一些解释在书上P35页。

  • 向量输入,矩阵输出

对单个数值调用 sqrt()函数得到的结果也是单个数值,如果我们将此函数应用到八元向量,则得到的输出结果也是八个数组成的向量。

但如果函数本身的返回值就是向量会怎么样呢?例如这里的z12():

> z12<-function(z)return(c(z,z^2))

对5使用函数z12(),将得到二元向量(5,25),如果我们将它应用在八元向量,则它生成16个数值:

> z12(x)
 [1]  1  2  3  4  5  6  7  8  1  4  9 16 25 36 49 64

把结果排列成8x2的矩阵可能会更自然,可以用matrix函数来实现:

> 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

但我们可以用sapply()(它是simplifyapply的缩写)来简化这一切。调用sapply(x,f)即可对x的每一个元素使用函数f(),并将结果转化为矩阵。下面是一个例子:

> 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

我们得到2x8而不是8x2维的矩阵,但它同样是有用的。
后续将进一步讨论sapply()函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值