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

2.6 向量化运算符

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

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

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

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

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

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

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

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

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

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

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

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

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

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

时间: 2024-08-01 21:08:21

《R语言编程艺术》——2.6 向量化运算符的相关文章

《R语言编程艺术》——1.3 函数入门

1.3 函数入门 和大多数编程语言一样,R语言编程的核心是编写"函数".函数就是一组指令的集合,用来读取输入.执行计算.返回结果.我们先定义一个函数oddcount(),以此简单介绍函数的用法.这个函数的功能是计算整数向量中奇数的个数.一般情况下,我们会用文本编辑器编写好函数代码并保存在文件中,不过在这个简单粗略的例子中,我们只需要在R的交互模式中一行行输入代码.接下来,我们还会在几个测试案例中调用这个函数: 首先,我们告诉R想定义一个名为oddcount的函数,该函数有一个参数x.左

《R语言编程艺术》——导读

前言 R是一种用于数据处理和统计分析的脚本语言,它受到由AT&T实验室开发的统计语言S的启发,且基本上兼容于S语言.S语言的名称代表统计学(statistics),用来纪念AT&T开发的另一门以一个字母命名的编程语言,这就是著名的C语言.后来一家小公司买下了S,给它添加了图形用户界面并命名为S-Plus. 由于R是免费的,而且有更多的人贡献自己的代码,R语言变得比S和S-Plus更受欢迎.R有时亦称为GNU S,以反映它的开源属性.(GNU项目是开源软件的一个重要集合.) 为什么在统计工作

《R语言编程艺术》——第2章 2.0 向量

第2章 2.0 向量 R语言最基本的数据类型是向量(vector).第1章已经给出了向量的一些例子,本章将详细介绍向量.首先考察向量与R语言的其他数据类型之间的关系.与C语言家族不同,R语言中,单个数值(标量)没有单独的数据类型,它只不过是向量的一种特例.而另一方面,R语言中矩阵是向量的一种特例,这一点与C语言家族相同.接下来我们会用大量时间关注以下话题:循环补齐:在一定情况下自动延长向量.筛选:提取向量子集.向量化:对向量的每一个元素应用函数.这些运算是R编程的核心,在本书的其他部分也会经常提

《R语言编程艺术》——1.4 R语言中一些重要的数据结构

1.4 R语言中一些重要的数据结构 R有多种数据结构.本节将简单介绍几种常用的数据结构,使读者在深入细节之前先对R语言有个大概的认识.这样,读者至少可以开始尝试一些很有意义的例子,即使这些例子背后更多的细节还需要过一段时间才能揭晓.1.4.1 向量,R语言中的战斗机 向量类型是R语言的核心.很难想象R语言代码或者R交互式会话可以一点都不涉及向量. 向量的元素必须属于某种"模式"(mode),或者说是数据类型.一个向量可以由三个字符串组成(字符模式),或者由三个整数元素组成(整数模式),

《R语言编程艺术》——2.4 常用的向量运算

2.4 常用的向量运算 接下来将介绍一些常用的向量运算,包括算术和逻辑运算.向量索引以及一些创建向量的有用方法.然后将给出两个使用这些运算的扩展案例.2.4.1 向量运算和逻辑运算记住R是一种函数式语言,它的每一个运算符,包括下例中的+,实际上也是函数. 再回顾一次,标量实际上是一元向量,因此向量也可以相加,+算子按元素逐一进行运算. 如果你熟悉线性代数,当将两个向量相乘时,你也许会对所发生的感到惊讶. 但请记住,由于*函数的使用方式,实际上是元素和元素相乘.上例结果中的第一个元素5,是x的第一

《R语言编程艺术》——2.1 标量、向量、数组与矩阵

2.1 标量.向量.数组与矩阵 在许多编程语言中,向量与标量(即单个数值)不同.例如,考虑下面的C代码: 这段代码请求编译器给一个x的整型变量x分配空间,并给一个名为y的三元素整型数组(C语言中的术语,类似于R中的向量)分配内存空间.但在R中,数字实际上被当做一元向量,因为数据类型里没有标量.R语言中变量类型称为模式(mode).回顾第1章,同一向量中的所有元素必须是相同的模式,可以是整型.数值型(浮点数).字符型(字符串).逻辑型(布尔逻辑).复数型等等.如果在程序中查看变量x的类型,可以调用

《R语言编程艺术》——1.7 获取帮助

1.7 获取帮助 有很多种资源可以帮你学习关于R的更多知识,其中包括R自身的一些工具,当然,还有网上的资料. 开发者们做了很多工作使R更加自文档化.下面我们将介绍一些R内置的帮助工具,以及互联网上的资源.1.7.1 help()函数 想获取在线帮助,可调用help().例如,要获取seq()函数的信息,就键入下面的命令: 1.7.2 example()函数 每个帮助条目都附带有例子.R的一个非常好用的特性是,example()函数会为你运行例子代码.示例如下: sep()函数可以生成多种等差数值

《R语言编程艺术》——3.4 增加或删除矩阵的行或列

3.4 增加或删除矩阵的行或列 严格来说,矩阵的长度和维度是固定的,因此不能增加或删除行或列.但是可以给矩阵重新赋值,这样可以得到和增加或删除一样的效果.3.4.1 改变矩阵的大小 回忆之前通过重新赋值改变向量大小的方法: 第一个例子里,x原来长度为5,通过拼接和重新赋值,将其长度变为6.事实上我们没有改变x的长度,而是生成一个新的向量,然后赋值给x. 注意 重新赋值的过程可能会在用户看不见的情况下进行,在14章我们将会介绍.例如,即使是x[2]<-12这种小操作事实上都是一个重新赋值的过程.

《R语言编程艺术》——2.12 关于c()的更多内容

2.12 关于c()的更多内容 在本节中,我们将讨论与连接函数c()相关的一些其他内容,有时经常用到.如果传递到c()中的参数有不同的类型,则它们将被降级为同一类型,该类型最大限度地保留它们的共同特性,如下所示: 在第一个例子中,我们混合了整数型和字符型,R会选择把它们都转换为后者的类型.在第二个例子中,对于混合的表达式,R认为列表类型有较低的优先级.本书4.3节将对这一点作深入探讨.你可能不会写如此组合的代码,但你可能会遇到发生这种情况的代码,因此理解它的效果显得尤为重要.另一个需要注意的关键