《R语言编程艺术》——3.2 一般矩阵运算

3.2 一般矩阵运算

前面介绍了创建矩阵的基本方法,现在我们来看一些常用的矩阵运算,包括线性代数运算、矩阵索引和矩阵元素筛选。
3.2.1 线性代数运算
你可以对矩阵进行各种线性代数运算,比如矩阵相乘、矩阵数量乘法和矩阵加法。针对以前例子中的y,以下为这三种运算的实例:

关于矩阵线性代数运算的更多细节请参见8.4节。
3.2.2 矩阵索引
2.4.2节中的向量运算同样适用于矩阵,例如:

这里我们提取了矩阵z中第2、3列的所有元素组成了一个子矩阵。
下面的例子提取的是矩阵的行:

还可以对一个矩阵的子矩阵进行赋值:

这里给y的第1、3行赋了新的值。
下面是另一个给子矩阵赋值的例子:

向量的负值索引用来排除掉某些元素,这种操作同样适用于矩阵。

命令第二行的意思是,取出矩阵y中除第二行外的所有行。
3.2.3 扩展案例:图像操作
图像文件本质上就是矩阵,因为像素点也都是按行和列排列的。一张灰度图像会把每一个像素点的亮度存储为矩阵的一个元素。例如,图像中位于第28行、第88列的像素点的灰度值就存储在矩阵的第28行、第88列。如果图像是彩色的话,就需要三个矩阵来存储,分别记录红、黄、蓝的强度值。这里我们只以灰度图像为例。
以一张拉什莫尔山国家纪念公园的照片为例,我们用pixmap包读取图像。(附录B介绍了下载和安装R包的方法。)

读取文件mtrush1.pgm,并返回一个pixmap类的对象。再把这个对象在R里画出来,如图3-1所示。

我们来看一下pixmap类的组成内容:

pixmap类属于S4类型,它用符号@来访问各个组件,而不是用符号$。S3和S4的问题将在第9章讨论,不过这里最关键的是灰度矩阵mtrush1@grey。在这个例子里,这个矩阵有194行和259列。
这个例子的灰度是用0.0到1.0之间的数值表示的,0.0表示黑色,1.0表示白色,中间值代表不同程度的灰色。例如,图片第28行、第88列的点非常亮。

为了演示矩阵操作,我们将罗斯福总统的脸覆盖上(对不起了,总统先生,我对你没有个人恩怨)。使用R中locator()函数来找到需要盖住部分的行号和列号。当调用这个函数时,R会等待用户点击图片上的任意点,然后返回该点的准确坐标。用这种方式可以找到罗斯福总统的脸对应区域是从84行到163行,从135列到177列。(注意,pixmap对象的行编号和locator()是相反的:pixmap是自上而下递增的,而locator()恰恰相反。)于是,为了把这部分图像覆盖上,我们把这一区域的所有像素点取值设为1.0。

效果如图3-2所示。

如果只是想将罗斯福总统的脸模糊掉,而不是去掉,可以在图片上增加随机噪声。代码如下:

如注释所显示的,我们生成随机噪声,然后把目标像素点矩阵和噪声进行加权平均。参数q控制噪声的权重,q值越大就越模糊。随机噪声取自U(0,1),即区间(0,1)上的均匀分布。注意,下面是矩阵操作:

效果如图3-3所示。

3.2.4 矩阵元素筛选
和向量一样,矩阵也可以做筛选。但是需要注意一下语法上的不同。首先来看一个简单的例子:

下面来分析一下这条命令,正如我们在第2章所讲那样:

为了提高性能,需要注意的是,计算j时使用的是完全向量化运算。这是因为:
x[,2]是向量。
运算符>=用于比较两个向量。
数值3被自动重复,变成一个由数值3组成的向量。
还需要注意,虽然这个例子中j是通过x定义且用于提取x中的元素,但事实上筛选规则可以基于除被筛选变量之外的变量。以下例子同样使用上述的x:

表达式 z 2 ==1用于判断z的每个元素是否是奇数,返回的结果是(TRUE, FALSE, TRUE)。因此我们提取出了x的第一、三行。
再看另外一个例子:


这里也是同样的做法,但是使用了稍微复杂的条件来提取矩阵的行。(用类似的方式可以提取列或子矩阵。)首先表达式m[,1] > 1把m的第一列的每个元素同1进行比较,返回(FALSE,TRUE,TRUE)。类似的是,第二个表达式m[,2] > 5返回(FALSE,FALSE,TRUE)。对(FALSE,TRUE,TRUE)和(FALSE,TRUE,TRUE)进行逻辑“与”运算,得到(FALSE,FALSE,TRUE)。以运算后的向量为行索引,得到矩阵m的第三行。
注意,这里需要使用 & 运算符,而不是 &&,前者是向量的逻辑“与”运算,后者是用于if语句的标量逻辑“与”运算。想了解更多可以参见7.2节中的运算符列表。
细心的读者可能注意到前面的例子中有一些反常的地方。我们要得到的是一个1行2列的子矩阵,可是返回的却是一个由两个元素组成的向量。元素是正确的,可是数据类型却不对。如果把返回值输入到其他的矩阵函数里可能会导致错误。解决办法是通过设定参数drop,告诉R让返回结果保持数据的二维属性。3.6节会介绍如何避免意外降维,并详细讲解drop的用法。
由于矩阵也是向量,所以向量的运算也适用于矩阵。例如:

这行命令说明,从向量索引的角度来看,m的第1、3、5、6个元素大于2。第5个元素指的是m第2行第2列的元素,即10,的确比2大。
3.2.5 扩展案例:生成协方差矩阵
这个例子演示row()和col()函数,这两个函数的参数都是矩阵。例如对于矩阵a,row(a[2,8])返回a中对应元素的行号,即2。然而,显然我们知道row(a[2,8])在第2行,那么这个函数有什么用途呢?
先来看一个例子。如果我们想要用MASS库的mvrnorm()函数生成多元正态分布的随机数,需要指定协方差矩阵。协方差矩阵是对称的,就是说矩阵中第1行第2列的元素等于第2行第1列的元素。
假如我们在处理一个n元正态分布,它的协方差矩阵有n行n列。我们希望这n个随机变量方差都为1,每两个变量间的相关性都是rho。例如当n=3,rho=0.2时,需要的矩阵就是:

下面就是生成这种矩阵的代码:

下面来解释它的运算过程。首先col()返回的是矩阵元素的列号,和row()功能相似。然后第三行的row(m)返回一个由整数组成的矩阵,每个整数代表矩阵m中对应元素的行号。例如:

因此表达式row(m) == col(m)返回一个由FALSE和TRUE组成的矩阵,矩阵的对角线位置是TRUE,其他位置是FALSE。再次提醒一下读者,本例中的二目运算符"=="是一个函数,row()和col()也是函数。因此,下面这个表达式:

会作用到矩阵m的每一个元素上,最后返回一个由FALSE和TRUE组成的矩阵,其行数和列数与m的相同。表达式ifelse()同样是一个函数调用。

在本例中,刚才提到的由TRUE和FALSE组成的矩阵传递给ifelse()函数做参数,返回一个矩阵,对角线元素为1,其他位置为0。

时间: 2024-09-14 21:05:13

《R语言编程艺术》——3.2 一般矩阵运算的相关文章

《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语言编程艺术》——2.1 标量、向量、数组与矩阵

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

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

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

《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节将对这一点作深入探讨.你可能不会写如此组合的代码,但你可能会遇到发生这种情况的代码,因此理解它的效果显得尤为重要.另一个需要注意的关键

《R语言编程艺术》——1.2 第一个R会话

1.2 第一个R会话 用数字1.2.4生成一个简单的数据集(用R的说法就是"向量"),将其命名为x: R语言的标准赋值运算符是<-.也可以用=,不过并不建议用它,因为在有些特殊的情况下它会失灵.注意,变量的类型并不是固定不变的.在这里,我们把一个向量赋值给x,也许之后会把其他类型的值赋给它.我们会在1.4节介绍向量和其他类型.c表示"连接"(英文是concatenate).在这里,我们把数字1.2.4连接起来.更精确地说,连接的是分别包含三个数字的三个一元向量