《R语言编程艺术》——3.3 对矩阵的行和列调用函数

3.3 对矩阵的行和列调用函数

*apply()函数系列是R中最受欢迎同时也是最常用的,该函数系列包括apply()、tapply()和lapply()。这里我们主要介绍apply()。apply()函数允许用户在矩阵的各行或各列上调用指定的函数。
3.3.1 使用apply()函数
以下是apply()函数的一般形式:

参数解释如下:
m 是一个矩阵。
dimcode 是维度编号,若取值为1代表对每一行应用函数,若取值为2代表对每一列应用函数。
f是应用在行或列上的函数。
fargs是f的可选参数集。
例如,对矩阵z的每一列应用函数mean():

本例也可以用colMeans()函数直接实现,不过这里主要为了提供使用apply()的简单示例。
apply()里也可以使用用户自己定义的函数,就和使用R内部函数(比如mean())一样。下面是使用自定义函数f的例子:

f()函数把一个向量除以(2,8)。(如果向量x的长度大于2,那么(2,8)就会循环补齐)。apply()函数则对z的每一行分别调用f()。z的第一行是(1,4),所以在调用f()时,形式参数x对应的实际参数是(1,4)。然后R计算(1,4)/(2,8)的值,这在R中是向量对应元素运算,得到(0.5,0.5)。对其他两行的计算与此类似。
你可能会惊讶,所得结果y是一个2×3的矩阵而非3×2的。第一行的计算结果(0.5, 0.5)构成apply()函数输出结果的第一列,而不是第一行。这就是apply()函数的默认方式。如果所调用的函数返回的是一个包含k个元素的向量,那么apply()的结果就有k行。如果需要的话,可以使用转置函数t(),例如:

如果所调用的函数只返回一个标量(即单元素向量),那么apply()的结果就是一个向量,而非矩阵。
在用apply()时,待调用的函数至少需要一个参数。上例中,f()的形式参数在这里对应的实际参数就是矩阵的一行(或一列)。有时,待调用函数需要多个参数,用apply()调用这类函数时,需要把这些额外的参数列举在函数名字后面,用逗号隔开。
例如,我们有一个由0和1组成的矩阵,想要生成如下向量:向量每个元素对应矩阵的每行,如果该行前d个元素中1较多,向量的对应元素就取1,反之取0。其中d是可以变的参数。程序可以这样写:

这里3和2是函数copymaj()中形式参数d的实际取值。矩阵的第一行是(1,0,1,1,0),当d取3时,前d个元素是(1,0,1)。1占多数,因此copymaj()返回1。所以apply()返回的第一个元素就是1。
使用apply()函数并不像很多人以为的那样,能使程序的运行速度加快。其优点是使程序更紧凑,更易于阅读和修改,并且避免产生使用循环语句时可能带来的bug。此外,并行运算是R目前发展的方向之一,apply()这类函数会变得越来越重要。例如,snow包中的clusterApply()函数能够把子矩阵的数据分配到多个网络节点上,在每个网络节点上对子矩阵调用给定的函数,达到并行计算的目的。
3.3.2 扩展案例:寻找异常值
在统计学中,“异常值”(outlier)指的是那些和大多数观测值离得很远的少数点。所以异常值要么是有问题(例如数字写错了),要么是不具有代表性(例如比尔盖茨的收入和华盛顿州居民的收入相比)。检测异常值有很多方法,我们这里构造一个非常简单的方法。
假如矩阵rs用来存储零售业销售数据,每行对应一家商店,一行里的观测值对应每天的销售数据。我们用非常简单的方法识别出每家商店数据中偏离最远的观测值,也就是与中位数差别最大的观测值。代码如下:

那么上述中的findols(rs)是如何运作的?首先需要定义一个函数,作为调用apply()函数时的参数。
该函数要应用于销售数据矩阵的每一行,并返回该行中最异常的元素所在位置。函数findol()就是为完成此目的而定义的,请看代码的第4、5行。(注意,我们在一个函数的内部又定义了另一个函数。如果内部函数很短的话,这么做是很常见的。)在表达式xrow-mdn中,向量xrow减去单元素向量mdn,而前者的长度通常大于1,因此在做向量减法运算之前,mdn被循环补齐(recycling),扩展到与xrow的长度一致。
代码第五行使用R函数which.max(),而不是max()。因为max()返回的是向量元素的最大值,而which.max()返回最大值所在位置(即索引)。这正是我们需要的。
最后在第七行,对x的每一行调用findol(),得到各行“异常值”所在位置。

时间: 2024-08-19 08:37:10

《R语言编程艺术》——3.3 对矩阵的行和列调用函数的相关文章

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

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

《R语言编程艺术》——3.1 创建矩阵

3.1 创建矩阵 矩阵的行和列的下标都从1开始.例如矩阵a左上角的元素记作a[1, 1].矩阵在R中是按列存储的,也就是说先存储第一列,再存储第二列,以此类推,如2.1.3小节所示. 创建矩阵的方法之一就是使用matrix()函数: 这里把第一列(即1和2)与第二列(3和4)连接在一起.因此数据是(1,2,3,4).然后我们给出行数和列数.由于R是按列存储的,这就决定了这四个数在矩阵中的位置. 上例指定了矩阵中全部的4个元素,因此没必要同时设定列数ncol和行数nrow这两个参数,只需要给出其中

《R语言编程艺术》——3.7 矩阵的行和列的命名问题

3.7 矩阵的行和列的命名问题 访问矩阵元素最直接的方法是通过行号和列号,但也可以使用行名与列名.例如: 如上例所示,这些名称可以用来访问指定的列.rownames()函数的功能与此类似.一般在编写R代码时,给行和列命名并不是那么重要,但在分析某些数据时会很有用.

《R语言编程艺术》——第3章 3.0 矩阵和数组

第3章 3.0 矩阵和数组 矩阵(matrix)是一种特殊的向量,包含两个附加的属性:行数和列数.所以矩阵也和向量一样,有模式的概念,例如数值型和字符型.(但反过来,向量却不能看作是只有一列或一行的矩阵.)数组(array)是R里更一般的对象,矩阵是数组的一个特殊情形.数组可以是多维的.例如一个三维的数组可以包含行.列和层(layer),而一个矩阵只有行和列两个维度.本章主要讨论矩阵,本章最后一节会简述更高维的数组.R的强大之处就在于它丰富的矩阵运算.本章主要讲述这些运算,尤其注重类似于向量的取

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

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

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

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

《R语言编程艺术》——3.5 向量与矩阵的差异

3.5 向量与矩阵的差异 在本章开始的时候,我说过矩阵就是一个向量,只是多了两个属性:行数和列数.这里,我们再深入说明这个问题.考虑以下例子: 因为z是向量,因此我们可以求它的长度: 换句话说,从面向对象编程的角度说,矩阵类(matrix class)是实际存在的.如第1章所说,R的大部分类都是S3类,用$符号就可访问其各组件.矩阵类有一个dim属性,是一个由矩阵的行数和列数组成的向量.本书第9章讲详细介绍关于类的更多细节问题. 以用dim()函数访问dim属性: 这些其实都是对dim函数的一个

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

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

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

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