北京大学R语言教程(李东风)第12章: R矩阵和数组

矩阵用matrix函数定义,实际存储成一个向量,根据保存的行数和列数对应到矩阵的元素,
存储次序为按列存储。
定义如

A <- matrix(11:16, nrow=3, ncol=2); print(A)
##      [,1] [,2]
## [1,]   11   14
## [2,]   12   15
## [3,]   13   16
B <- matrix(c(1,-1, 1,1), nrow=2, ncol=2, byrow=TRUE); print(B)
##      [,1] [,2]
## [1,]    1   -1
## [2,]    1    1

matrix()函数把矩阵元素以一个向量的形式输入,
nrowncol规定行数和列数,向量元素填入矩阵的缺省次序是按列填入,
byrow=TRUE选项可以转换成按行填入。

nrow()ncol()函数可以访问矩阵的行数和列数,如

## [1] 3
## [1] 2

矩阵有一个dim属性,内容是两个元素的向量,
两个元素分别为矩阵的行数和列数。dim属性可以用dim()函数访问。如

## $dim
## [1] 3 2
## [1] 3 2

函数t(A)返回A的转置。

12.2 矩阵子集

A[1,]取出A的第一行,变成一个普通向量。
A[,1]取出A的第一列,变成一个普通向量。
A[c(1,3),1:2]取出指定行、列对应的子矩阵。

##      [,1] [,2]
## [1,]   11   14
## [2,]   12   15
## [3,]   13   16
## [1] 11 14
## [1] 11 12 13
##      [,1] [,2]
## [1,]   11   14
## [2,]   13   16

colnames()函数可以给矩阵每列命名,
也可以访问矩阵列名,
rownames()函数可以给矩阵每行命名,
也可以访问矩阵行名。如

colnames(A) <- c('X', 'Y')
rownames(A) <- c('a', 'b', 'c')
A
##    X  Y
## a 11 14
## b 12 15
## c 13 16

矩阵可以有一个dimnames属性,
此属性是两个元素的列表(列表见稍后部分的介绍),
两个元素分别为矩阵的行名字符型向量与列名字符型向量。
如果仅有其中之一,缺失的一个取为NULL

有了列名、行名后,矩阵下标可以用字符型向量,

##  a  b  c 
## 14 15 16
##  X  Y 
## 12 15
##  a  c 
## 14 16

注意在对矩阵取子集时,
如果取出的子集仅有一行或仅有一列,
结果就不再是矩阵而是变成了R向量,
R向量既不是行向量也不是列向量。
如果想避免这样的规则起作用,
需要在方括号下标中加选项drop=FALSE

##    X
## a 11
## b 12
## c 13

取出了A的第一列,
作为列向量取出,
所谓列向量实际是列数等于1的矩阵。
如果用常量作为下标,
其结果维数是确定的,不会出问题;
如果用表达式作为下标,
则表达式选出零个、一个、多个下标,
结果维数会有不同,
drop=FALSE则是安全的做法。

矩阵也可以用逻辑下标取子集,比如

##    X  Y
## a 11 14
## b 12 15
## c 13 16
##  b  c 
## 15 16

矩阵本质上是一个向量添加了dim属性,
实际保存还是保存成一个向量,
其中元素的保存次序是按列填入,
所以,
也可以向对一个向量取子集那样,
仅用一个正整数向量的矩阵取子集。如

##    X  Y
## a 11 14
## b 12 15
## c 13 16
## [1] 11 13 15

为了挑选矩阵的任意元素组成的子集而不是子矩阵,
可以用一个两列的矩阵作为下标,
矩阵的每行的两个元素分别指定一个元素的行号和列号。

ind <- matrix(c(1,1, 2,2, 3,2), ncol=2, byrow=TRUE)
A
##    X  Y
## a 11 14
## b 12 15
## c 13 16
##      [,1] [,2]
## [1,]    1    1
## [2,]    2    2
## [3,]    3    2
## [1] 11 15 16

c(A)A[]返回矩阵A的所有元素。
如果要修改矩阵A的所有元素,
可以对A[]赋值。

对矩阵Adiag(A)访问A的主对角线元素组成的向量。
另外,若x为正整数值标量,diag(x)返回x阶单位阵;
x为长度大于1的向量,
diag(x)返回以x的元素为主对角线元素的对角矩阵。

12.3 cbind()rbind()函数

x是向量,cbind(x)x变成列向量,
即列数为1的矩阵,
rbind(x)x变成行向量。

x1, x2, x3是等长的向量,
cbind(x1, x2, x3)把它们看成列向量并在一起组成一个矩阵。
cbind()的自变量可以同时包含向量与矩阵,向量的长度必须与矩阵行数相等。

cbind(c(1,2), c(3,4), c(5,6))
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6
##    X  Y   
## a 11 14  1
## b 12 15 -1
## c 13 16 10

cbind()的自变量中也允许有标量,
这时此标量被重复使用。

##      [,1] [,2]
## [1,]    1    1
## [2,]    1   -1
## [3,]    1   10

rbind()用法类似,
可以等长的向量看成行向量上下摞在一起,
可以是矩阵与长度等于矩阵列数的向量上下摞在一起,
向量长度为1也可以。

12.4 矩阵运算

12.4.1 四则运算

矩阵可以与标量作四则运算,结果为每个元素进行相应运算,如

##    X  Y
## a 11 14
## b 12 15
## c 13 16
##    X  Y
## a 13 16
## b 14 17
## c 15 18
##     X   Y
## a 5.5 7.0
## b 6.0 7.5
## c 6.5 8.0

当运算为矩阵乘以一个标量时,
就是线性代数中的矩阵的数乘运算。

两个同形状的矩阵进行加、减运算,
即对应元素相加、相减,
A + BA - B表示,如

##      X    Y
## a 18.5 23.0
## b 20.0 24.5
## c 21.5 26.0
##     X    Y
## a 7.5  9.0
## b 8.0  9.5
## c 8.5 10.0

这就是线性代数中矩阵的加、减运算。

对两个同形状的矩阵,
*表示两个矩阵对应元素相乘(注意这不是线性代数中的矩阵乘法),
/表示两个矩阵对应元素相除。

##      X     Y
## a 71.5 112.0
## b 84.0 127.5
## c 97.5 144.0
##          X        Y
## a 2.363636 2.285714
## b 2.333333 2.266667
## c 2.307692 2.250000

12.4.2 矩阵乘法

%*%表示矩阵乘法而不是用*表示,
注意矩阵乘法要求左边的矩阵的列数等于右边的矩阵的行数。

##    X  Y
## a 11 14
## b 12 15
## c 13 16
##      [,1] [,2]
## [1,]    1   -1
## [2,]    1    1
##   [,1] [,2]
## a   25    3
## b   27    3
## c   29    3

12.4.3 向量与矩阵相乘

矩阵与向量进行乘法运算时,
向量按需要解释成列向量或行向量。
当向量左乘矩阵时,看成行向量;
当向量右乘矩阵时,看成列向量。

##      [,1] [,2]
## [1,]    1   -1
## [2,]    1    1
##      [,1] [,2]
## [1,]    2    0
##      [,1]
## [1,]    0
## [2,]    2
##      [,1]
## [1,]    2

注意矩阵乘法总是给出矩阵结果,
即使此矩阵已经退化为行向量、列向量甚至于退化为标量也是一样。
如果需要,可以用c()函数把一个矩阵转换成按列拉直的向量。

12.4.4 内积

x, y是两个向量,
计算向量内积,
可以用sum(x*y)表示。

A, B是两个矩阵,
ATB是广义的内积,
也称为叉积(crossprod),
结果是一个矩阵,
元素为A的每列与B的每列计算内积的结果。
ATB在R中可以表示为crossprod(A, B),
ATA可以表示为crossprod(A)
要注意的是,crossprod()的结果总是矩阵,
所以计算两个向量的内积用sum(x,y)而不用crossprod(x,y)

12.4.5 外积

R向量支持外积运算,
记为%o%,
结果为矩阵。
x %o% y的第i行第j列元素等于x[i]乘以y[j]。

##      [,1] [,2]
## [1,]    1   -1
## [2,]    2   -2
## [3,]    3   -3

这种运算还可以推广到x的每一元素与y的每一元素进行其它的某种运算,
而不限于乘积运算,可以用outer(x,y,f)完成,
其中f是某种运算,或者接受两个自变量的函数。

12.5 逆矩阵与线性方程组求解

solve(A)A的逆矩阵,如

##      [,1] [,2]
## [1,]  0.5  0.5
## [2,] -0.5  0.5

solve(A,b)求解线性方程组Ax=b中的x,

## [1] 1.5 0.5

求解了线性方程组

(1111)x=(12)

12.6 apply()函数

apply(A, 2, FUN)把矩阵A的每一列分别输入到函数FUN中,
得到对应于每一列的结果,如

D <- matrix(c(6,2,3,5,4,1), nrow=3, ncol=2); D
##      [,1] [,2]
## [1,]    6    5
## [2,]    2    4
## [3,]    3    1
## [1] 11 10

apply(A, 1, FUN)把矩阵A的每一行分别输入到函数FUN中,
得到与每一行对应的结果,如

## [1] 5.5 3.0 2.0

如果函数FUN返回多个结果,
apply(A, 2, FUN)结果为矩阵,
矩阵的每一列是输入矩阵相应列输入到FUN的结果,
结果列数等于A的列数。如

##      [,1] [,2]
## [1,]    2    1
## [2,]    6    5

如果函数FUN返回多个结果,
为了对每行计算FUN的结果,
结果存入一个与输入的矩阵行数相同的矩阵,
应该用t(apply(A, 1, FUN))的形式,

##      [,1] [,2]
## [1,]    5    6
## [2,]    2    4
## [3,]    1    3

12.7 多维数组

矩阵是多维数组(array)的特例。
矩阵是xij,i=1,2,,n,j=1,2,,m这样的两下标数据的存贮格式,
三维数组是xijk,i=1,2,,n,j=1,2,,m,k=1,2,,p这样的三下标数据的存贮格式,
s维数组则是有s个下标的数据的存贮格式。
实际上,
给一个向量添加一个dim属性就可以把它变成多维数组。

多维数组的一般定义语法为

数组名 <- array(数组元素, 
  dim=c(第一下标个数, 第二下标个数, ..., 第s下标个数))

其中数组元素的填入次序是第一下标变化最快,
第二下标次之,
最后一个下标是变化最慢的。
这种次序称为FORTRAN次序。

下面是一个三维数组定义例子。

ara <- array(1:24, dim=c(2,3,4)); ara
## , , 1
## 
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6
## 
## , , 2
## 
##      [,1] [,2] [,3]
## [1,]    7    9   11
## [2,]    8   10   12
## 
## , , 3
## 
##      [,1] [,2] [,3]
## [1,]   13   15   17
## [2,]   14   16   18
## 
## , , 4
## 
##      [,1] [,2] [,3]
## [1,]   19   21   23
## [2,]   20   22   24

这样的数组保存了xijk,i=1,2,j=1,2,3,k=1,2,3,4
三维数组ara可以看成是4个2×3矩阵。
取出其中一个如ara[,,2](取出第二个矩阵)

##      [,1] [,2] [,3]
## [1,]    7    9   11
## [2,]    8   10   12

多维数组可以利用下标进行一般的子集操作,
比如ara[,2, 2:3]
xijk,i=1,2,j=2,k=2,3的值,
结果是一个2×2矩阵:

##      [,1] [,2]
## [1,]    9   15
## [2,]   10   16

多维数组在取子集时如果某一维下标是标量,
则结果维数会减少,
可以在方括号内用drop=FALSE选项避免这样的规则发生作用。

类似于矩阵,
多维数组可以用一个矩阵作为下标,
如果是三维数组,矩阵就需要有3列,
四维数组需要用4列矩阵。
下标矩阵的每行对应于一个数组元素。

12.8 列表类型的数组

矩阵一般用于数值计算,
所以其元素一般是数值。
但是,
在更复杂的编程场景中,
可能需要在矩阵(或数组)元素中保存复杂结构,
比如,
每个元素是一个长度可变的向量。
这时,
可以将矩阵元素设为列表类型,
但访问其元素需要使用部分列表访问语法格式。

例如,
生成未初始化的列表类型的矩阵:

L <- matrix(list(), nrow=2, ncol=2); L
##      [,1] [,2]
## [1,] NULL NULL
## [2,] NULL NULL

给每个矩阵元素赋值为仅有一个元素的列表:

L[1,1] <- list(1:2)
L[1,2] <- list(3:5)
L[2,1] <- list(6:10)
L[2,2] <- list(11:15)
L
##      [,1]      [,2]     
## [1,] integer,2 integer,3
## [2,] integer,5 integer,5

元素为仅一个元素的列表:

## [[1]]
## [1] 11 12 13 14 15

为了访问元素的实际内容,需要继续用[[]]格式:

## [1] 11 12 13 14 15

但是,
这样每个矩阵元素必须为长度1的列表。下面的程序会出错

L[1,1] <- list(101:102, 103:104)
## Error in L[1, 1] <- list(101:102, 103:104) : 
##   number of items to replace is not 
##   a multiple of replacement length

需要写成:

L[1,1][[1]] <- list(101:102, 103:104)
L[1,1]
## [[1]]
## [[1]][[1]]
## [1] 101 102
## 
## [[1]][[2]]
## [1] 103 104

这样,(1,1)元素的实际内容仍是一个列表:

## [[1]]
## [1] 101 102
## 
## [[2]]
## [1] 103 104

访问其中的内容:

## [1] 101 102

所以,
如果矩阵元素是长度为1的列表,
则只要给L[1,1]赋值为一个长度为1的列表,
访问元素内容时用L[1,1][[1]]的语法。
如果需要在矩阵元素中保存长度大于1的列表,
就需要将元素的实际内容保存成一个长度为大于1的列表,
如上例,
这时L[1,1][[1]]是长度大于1的列表。

韭菜热线原创版权所有,发布者:风生水起,转载请注明出处:https://www.9crx.com/77955.html

(0)
打赏
风生水起的头像风生水起普通用户
上一篇 2023年10月31日 00:34
下一篇 2023年10月31日 00:43

相关推荐

  • 母亲传授的投资经验

    你的母亲可能传授了你可能不知道的宝贵投资经验。随着母亲节的临近和牛市的繁荣,这是重温她教给我的投资经验的绝佳时机。 就我个人而言,在我成长的过程中,我母亲对几乎所有事情都有自己的说法或答案……就像大多数母亲一样。每次回答“为什么?”这个问题时,她都会立即给出最聪明的答案: “…因为我说过”。 说真的,我的母亲是我的知识宝库,多年来对我很有帮助,直到晚年我才意…

    2024年5月14日
    2900
  • 连续6年获得最佳CTA的Florin Court Capital ,关于趋势跟踪策略的介绍

    FLorin Court 荣获《对冲基金杂志》颁发的2022 年及过去 2、3、4、5 和 6 年趋势追随者(另类市场 – 金融和大宗商品)类别最佳表现基金 CTA 和全权交易员奖(基于风险调整后的结果)。 Florin Court 作为另类市场趋势追随者的使命是最大限度地提高多元化收益并利用哥伦比亚利率、中国甲醇和加州碳排放等市场的强劲趋势。 该策略的平均…

    2023年7月19日
    10100
  • 新兴债务能源转型

    作者: Sergey Sobolev、 Mustafa Ulukan,24 年 3 月 7 日 执行摘要 在本文中,我们提出了一种为新兴国家向清洁能源生产转型提供融资的新方法。我们认为,温室气体 (GHG) 减排和投资回报两个方面都存在重大机遇。利用 2024 年新兴市场固定收益投资三十年经验的见解,我们的方法旨在促进与主权净零承诺一致的能源转型目标,同时还…

    2024年3月24日
    3100
  • 北京大学R语言教程第57章:用Rcpp帮助制作R扩展包

    R扩展包是把解决某种问题的可复用代码、文档整合在一起的最好的方法。写成R扩展包后,可以自己用,也可以利用CRAN分发。扩展包用户一般不用自己编译。 使用扩展包来组织程序,多个源程序、头文件之间的依赖关系可以自动得到处理。 扩展包提供了测试、文档和一致性检查的统一框架。 扩展包中代码可以仅有R程序,也可以包括C程序、C++程序、Fortran程序。如果仅有R代…

    2023年12月21日
    5500
  • 北京大学金融时间序列分析讲义第17章: ARCH模型

    这是原书(Tsay 2013)§4.5内容。 ARCH模型公式 (R. F. Engle 1982) 提出了ARCH模型(自回归条件异方差模型),这是对将波动率定义为条件标准差,第一次提出的波动率的理论模型。基本思想是: 资产收益率的扰动序列at=rt−E(rt|Ft−1)是前后不相关的, 但是前后不独立。 at的不独立性, 描述为Var(rt|Ft−1)=…

    2023年7月30日
    21200

发表回复

登录后才能评论
客服
客服
关注订阅号
关注订阅号
分享本页
返回顶部