《R语言编程艺术》——2.6 向量化运算符

2.6 向量化运算符

假设我们希望对向量x中的每一个元素使用函数f()。在很多情况下,我们可以简单地对x调用f()就能完成。
这可以简化我们的代码,不仅如此,还能将代码运行效率显著提高到数百倍甚至更多。
提高R代码执行速度的有效方法之一是向量化(vectorize),这意味着应用到向量上的函数实际上应用在其每一个元素上。
2.6.1 向量输入,向量输出
之前在本章你已经看到向量化运算的一些例子,即+和*运算符。另一个例子是>。
image

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

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

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

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

image

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

image

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

image

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

image

在这里定义的f(),我们希望c是一个标量,但实际上它当然是一个长度为1的向量。即使我们调用f()时给c指定的是单个数值,在f()计算x+c时,它也会通过循环补齐的方式延展为一个向量。因此对于本例中调用的f(1:3,1),x+c的值变为如右所示:
这带来了代码安全性的问题。f()中没有什么告知我们不能使用显式的向量给c赋值,例如:

image

你需要通过计算确认(4,16,36)是否的确是期望的输出。
如果你确实想把c限制为标量,则需要插入一些判断语句,比如这样:

image

2.6.2 向量输入,矩阵输出
到目前为止,我们涉及的向量化函数应用于标量时返回值也是标量。对单个数值调用sqrt()函数得到的结果也是单个数值,如果我们将此函数应用到八元向量,则得到的输出结果也是八个数组成的向量。
但如果函数本身的返回值就是向量会怎么样呢?例如这里的z12():

image

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

image

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

image

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值