矩阵是将数据按行和列组织数据的一种数据结构,相当于二维数组,如图4.14所示。与向量类似,矩阵的每个元素都拥有相同的数据类型。通常用列表示来自不同变量的数据,用行表示相同的数据。
在R语言中,矩阵在数据统计分析中尤为重要。矩阵运算是多元统计的核心,主成分分析、因子分析和聚类分析都离不开矩阵变换与运算。
图4.14 矩阵示意图
在R语言中,创建矩阵有以下几种方式,下面依次进行介绍。
创建一个向量,然后使用dim()函数设置矩阵的维数。这里,dim()函数主要用于获取或设置指定矩阵、数组或数据框的维数。
例如,创建一个3行5列的矩阵,示例代码如下:
1 x <- 1:15 2 dim(x) <- c(3,5) # 创建3行5列的矩阵 3 print(x)
运行程序,结果如图4.15所示。
图4.15 创建3行5列的矩阵
在R语言中,创建矩阵最快捷、常用的方法是使用matrix()函数,语法格式如下:
matrix(data=NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
参数说明如下。
data:表示矩阵的元素,默认值为NA,如果未给出元素值,则各元素值为NA。
nrow:表示矩阵的行数,默认值为1。
ncol:表示矩阵的列数,默认值为1。
byrow:布尔值,元素是否按行填充,默认按列填充。
dimnames:字符型向量,表示行名和列名的标签列表。
【例4.4】 创建简单矩阵 (实例位置:资源包\Code\04\04)
使用matrix()函数创建几个简单的矩阵。运行RStudio,编写如下代码。
运行程序,结果如图4.16所示。这里,首先创建了一个包含数字1~25的5×5(即5行5列)的矩阵;接着创建的是一个包含数字1~9的3×3的矩阵;然后创建了一个包含数字1~6的3×2按行填充的矩阵;最后创建了一个包含数字1~6的3×2按列填充的矩阵。
图4.16 创建简单矩阵
【例4.5】 创建学生成绩表 (实例位置:资源包\Code\04\05)
使用matrix()函数创建学生成绩表。运行RStudio,新建一个R Script脚本文件,编写如下代码。
运行程序,结果如图4.17所示。
图4.17 创建学生成绩表
在上述代码中,创建了一个4行3列的学生成绩表,并且按行填充,这样数据看上去更清晰。首先创建的是“甲”同学的“数学”“语文”“英语”成绩,然后是“乙”“丙”“丁”同学各科的成绩。通过dimnames参数设置了行标签为姓名,列标签为学科,其中使用了list()函数,该函数用于创建列表。
通过diag()函数可以创建对角矩阵和单位矩阵。语法格式如下:
diag(x=1,nrow,ncol)
参数说明如下。
x:表示矩阵、向量或一维数组。
nrow:表示可选参数,生成对角矩阵的行数。
ncol:表示可选参数,生成对角矩阵的列数。
【例4.6】 创建对角矩阵和单位矩阵 (实例位置:资源包\Code\04\06)
使用diag()函数创建对角矩阵和单位矩阵。运行RStudio,新建一个R Script脚本文件,编写如下代码。
1 # 创建对角矩阵 2 x <- 1:5 3 diag(x) 4 # 创建单位矩阵 5 x <- rep(1,5) 6 diag(x)
运行程序,结果如图4.18所示。
图4.18 创建对角矩阵和单位矩阵
从运行结果可知,单位矩阵与对角矩阵的区别是,对角矩阵的数据是重复的。创建单位矩阵应首先使用rep()函数创建一个包含重复值的向量,然后使用diag()函数创建矩阵就是单位矩阵。
矩阵索引用于访问矩阵中的元素,类似于向量元素。通过在方括号“[ ]”中指定元素所在行和列的位置(也称下标),便可以访问该元素。如x[i,j]可获取矩阵中第i行第j列的元素。
【例4.7】 获取矩阵中的元素 (实例位置:资源包\Code\04\07)
通过矩阵下标可以获取矩阵元素,下面获取学生成绩表中的元素。运行RStudio,编写如下代码。
运行程序,结果如图4.19所示。
图4.19 获取矩阵中的元素
矩阵编辑包括矩阵元素的添加、修改和删除,还需为矩阵行列命名。假设有如图4.20所示的矩阵,下面对其元素进行添加、修改和删除操作。
图4.20 原始矩阵
矩阵创建完成后,有时还需要对该矩阵添加一行或者一列,此时可以使用rbind()函数或cbind()函数。例如,在原始矩阵中添加一行和一列数据,示例代码如下:
1 mat <- matrix(1:9, nrow=3) # 创建原始矩阵 2 print(mat) 3 rbind(mat,c(10,20,30)) # 在原始矩阵mat后面添加一行 4 print(mat) 5 cbind(mat,c(10,20,30)) # 在原始矩阵mat后面添加一列 6 print(mat)
运行程序,结果如图4.21所示。
图4.21 矩阵元素添加
类似于向量,可以通过赋值运算修改矩阵中的元素。示例代码如下:
删除矩阵元素同样是通过赋值运算的方法实现的,原理是通过负整数索引访问矩阵中除了该位置的所有元素,也就是将要删除的矩阵元素排除在外,从而实现删除矩阵元素的功能。示例代码如下:
1 1 mat <- mat[-2, -2] # 删除第2行第2列 2 2 mat <- mat[-2,] # 删除第2行 3 3 mat <- mat[c(1,3,5),] # 删除多行
矩阵行列命名可以使用rownames()函数或colnames()函数。例如,设置行名为“甲”“乙”“丙”,列名为“语文”“数学”“英语”。示例代码如下:
1 rownames(mat) <- c("甲","乙","丙") 2 colnames(mat) <- c("语文","数学","英语")
本节主要介绍矩阵运算,包括矩阵加减运算、乘除运算、线性代数运算和统计计算等。
矩阵加减运算的规则为将两个矩阵对应的元素分别进行加减运算得到的矩阵。需要注意的是,在矩阵加减运算中,两个矩阵的维数必须一致,否则报错。
例如,创建两个矩阵,实现加减法运算,示例代码如下:
1 # 创建原始矩阵 2 m1 <- matrix(1:6, nrow=2) 3 print(m1) 4 m2 <- matrix(7:12, nrow=2) 5 print(m2) 6 print(m1+m2) # 矩阵加法运算 7 print(m1-m2) # 矩阵减法运算
运行程序,结果如图4.22所示。
图4.22 矩阵加减法运算
矩阵乘法运算是最有用的矩阵操作,广泛应用于网络理论、坐标转换等领域。除了前面介绍过的m1*m2,即两个矩阵对应元素分别相乘之外,还有多种乘法运算,下面详细进行介绍。
1)两个矩阵的乘除运算
矩阵乘除运算的规则为将两个矩阵对应的元素分别进行乘除运算得到的矩阵。同样,两个矩阵的维数必须一致,否则报错。
例如,矩阵m1和m2进行乘除运算,示例代码如下:
1 print(m1*m2) # 矩阵乘法运算 2 print(m1/m2) # 矩阵除法运算
运行程序,结果如图4.23所示。
图4.23 矩阵乘除法运算
2)矩阵与标量相乘
标量通常指一个单独的数。当矩阵与标量相乘时,矩阵中的每个元素都将与这个标量相乘。
例如,有如图4.24所示的m1矩阵,求其与标量10相乘的结果。示例代码如下:
1 m1 <- matrix(1:6, nrow=2) # 创建原始矩阵 2 print(m1) 3 m1 <- 10*m1 # 与标量相乘 4 print(m1)
运行程序,结果如图4.25所示。
在上述代码中,标量10与矩阵m1中的每个元素相乘,运算过程如下:
10*1=10 10*3=30 10*5=50 10*2=20 10*4=40 10*6=60
3)矩阵与向量相乘
当矩阵与向量相乘时,向量将被转换为行或列矩阵,以使两个参数相符。
例如,矩阵m1与向量相乘,示例代码如下:
1 # 创建一个向量 2 x <- 1:2 3 print(m1*x)
运行程序,结果如图4.26所示。运算过程如下:
1*1=1 1*3=3 1*5=5 2*2=4 2*4=8 2*6=12
图4.24 原始矩阵
图4.25 与标量10相乘的结果
图4.26 矩阵m1与向量相乘的结果
4)使用%*%运算符进行矩阵乘法运算
运算符%*%也可用于矩阵乘法运算,它是线性代数的乘法。与使用“*”的矩阵乘法运算不同,它的计算规则为将第一个矩阵的每一行与第二个矩阵的每一列相乘,并将结果累加,得到乘积矩阵的每一个元素。需要注意的是,条件是第一个矩阵的列数与第二个矩阵的行数相等。
示例代码如下:
1 m1 <- matrix(1:6, nrow=2) 2 m2 <- matrix(7:12, nrow=3) 3 print(m1%*%m2)
运行程序,结果如图4.27所示。
图4.27 %*%运算符的矩阵乘法
运算过程如下:
1*7+3*8+5*9=76 1*10+3*11+5*12=103 2*7+4*8+6*9=100 2*10+4*11+6*12=136
线性代数是一门应用性很强,理论知识非常抽象的学科,其中很多定理、性质和方法在数据分析中都有着重要作用。在R语言中提供了很多用于线性代数运算的函数,具体介绍如下。
1)矩阵求逆
使用solve()函数可获得逆矩阵。例如,solve(a, b, ...)用于求解a %*% x = b,当参数b省略时,b会被设为单位矩阵,此时solve()函数返回a的逆矩阵。如果a是不可逆的,那么将会报错。
示例代码如下:
1 m <- diag(1:5) # 创建对角矩阵 2 solve(m) # 矩阵求逆
运行程序,结果如图4.28所示。
图4.28 矩阵求逆
2)矩阵转置
使用t()函数可将矩阵转置,即将原有矩阵的行变成列。例如,将3行4列的矩阵转置成4行3列,示例代码如下:
1 m <- matrix(1:12,nrow=3,ncol=4) # 原始矩阵 2 print(m) 3 t(m) # 矩阵转置
运行程序,结果如图4.29所示。
图4.29 矩阵转置
3)特征值分解
eigen()函数用于计算矩阵的特征值和特征向量。其中,特征值是缩放特征向量的因子,示例代码如下:
1 m <- matrix(1:9,nrow=3,ncol=3) # 原始矩阵 2 print(m) 3 eigen(m) # 特征值和特征向量
运行程序,结果如图4.30所示。
4)奇异值分解
奇异值分解(SVD)是线性代数中一种重要的矩阵分解,它可将矩阵分解为奇异值和奇异向量。每个实数矩阵都有奇异值分解,但不一定都有特征分解。
在R语言中,svd()函数用于对矩阵进行奇异值分解,示例代码如下:
1 m <- matrix(c(15,12,30,9,-7,-2), nrow = 2, byrow = TRUE) # 原始矩阵 2 svd.value <- svd(m, nu = 2, nv = 3) # 奇异值分解 3 print(svd.value)
运行程序,结果如图4.31所示。从运行结果得知svd()函数返回了3个值。
svd()函数返回的3个值具体说明如下。
d:返回数字,表示矩阵m的奇异值,即矩阵d的对角线上的元素。
u:返回正交阵u。
v:返回正交阵v。
图4.30 特征值分解
图4.31 奇异值分解
5)Cholesky分解
在R语言中,chol()函数用于计算实对称矩阵的Cholesky分解。这里,“实”代表矩阵元素都是实数;“对称”代表矩阵元素沿主对角线对称相等,即A(i,j)=A(j,i)。示例代码如下:
1 x <- 1:4 2 chol(diag(x))
运行程序,结果如图4.32所示。
6)行列式
在R语言中,使用det()函数可以计算指定矩阵的行列式。示例代码如下:
1 x <- matrix(c(2, 13, 26, -1, 7, -6,9,33,-8), 3, 3) # 原始矩阵 2 print(x) 3 det(x) # 矩阵的行列式
运行程序,结果如图4.33所示。
图4.32 Choleskey分解
图4.33 行列式
进行矩阵统计计算,会用到求和函数sum()、平均值函数mean()、最大值函数max()、最小值函数min()等。
1)sum()函数
矩阵求和主要使用sum()函数,可以按行求和,也可以按列求和。示例代码如下:
1 m <- matrix(1:15, nrow=5) # 创建原始矩阵 2 print(m) 3 m1 <- sum(m[,2]) # 按列求和 4 print(m1) 5 m2 <- sum(m[2,]) # 按行求和 6 print(m2)
运行程序,结果如图4.34所示。
图4.34 按列和按行求和
2)mean()函数
矩阵求平均值常用mean()函数,可以按行求平均值,也可以按列求平均值。
例如,求第2列的平均值,示例代码如下:
1 m3 <- mean(m[,2]) 2 print(m3)
运行程序,结果为8。
3)max()函数
矩阵求最大值常用max()函数,可以求每行的最大值,也可以求每列的最大值。
例如,求第2列的最大值,示例代码如下:
1 m4 <- max(m[,2]) 2 print(m4)
运行程序,结果为10。
4)min()函数
矩阵求最大值常用min()函数,可以求每行的最小值,也可以求每列的最小值。例如,求第2列的最小值,示例代码如下:
1 m5 <- min(m[,2]) 2 print(m5)
运行程序,结果为6。