机器学习第4章第2节 : R语言科学计算
分类(组统计)
R语言分类统计主要包括数据分类整理,统计函数定义,数据分类的3个过程.
准备分组数据
fruit_class <- c("苹果","梨子","橘子","草莓","苹果","橘子","橘子","草莓","橘子","草莓")
fruit_price <- c(3.5,2.5,1.5,5.5,4.2,3.2,2.8,4.8,2.9,5.8)
平均价格统计
通过在tapply函数中指定mean函数为其参数,可实现分组求平均值,计算结果分为两行,第一行是组名,第二行是tapply函数最后一个函数参数的运算结果.示例如下:
tapply(fruit_price,fruit_class,mean)
最低价格统计
通过在tapply函数中指定min函数为其参数,可实现分组求最小值,示例如下
tapply(fruit_price,fruit_class,min)
标准差统计
通过在tapply函数中指定sd函数为其参数,可实现分组求标准差,示例如下:
tapply(fruit_price,fruit_class,sd)
标准误
标准误即样本均数的标准差,是描述均数抽样分布的离散程度及衡量均数抽样误差大小的尺度,反映的是样本均数之间的变异.
但是! 标准误不是标准差,而是样本均值的标准差是用来衡量抽样误差的,其计算公式为:
其中,S为样本标准差.标准误越小表明样本统计量与总体参数的值越接近,样本对总体越有代表性用样本统计量推断总体参数的可靠程度越大.
我们可以通过在tapply函数中自动自定义函数stderr为其参数来实现分组求标准误示例如下:
stderr <- function(x) sqrt(var(x) / length(x)) #自定义stderr函数
tapply(fruit_price,fruit_class,stderr)
数组与矩阵基础
R提供了简单的工具以处理数组和矩阵
数组与矩阵的维数
数组与矩阵的维数是其行向量(或列向量)生成的向量空间的维度,可用维数向量表示格式为(行数 x 列数),元素都非负.
通常使用dim函数来定义数组维度,示例如下:
my_num <- c(11,22,34,71,14,68,21,22,11,34)
dim(my_num) <- c(2,5) #指定数组维度为2行5列
my_num
dim(my_num) <- c(10) #指定数组维度为1行10列(需要与对象长度匹配)
my_num
dim(my_num) <- c(6) #错误
my_num
dim(my_num) <- c(15) #错误
my_num
切片
切片是操作多维数据(矩阵,数组等)的主要手段,它以索引为参数获取数据或矩阵的一部分,比如:想要得到多位数组的一个切片,则以索引为下标进行访问取得某块数组.使用[索引]格式的参数对数据和矩阵完成切片操作.
索引形式1
[index1,index2,index3,……,index n]. index1,index2等分别标明了元素在相应维数的索引,将索引组合成完成的位置,标注需要取出的元素,进行切片,形成数组块.比如:数组Array的大小为3x5,Array[2,4]表示第2行第4列元素.
索引形式2
[c(index1,index2,index3,……,index n)]. index1,index2等n个整数标注了元素的位置,将这些标注的元素取出后,组成数组块,这些元素以列为顺序排列.比如:数组Array的大小为3x2(3行2列),切片操作Array[c(1,2,3,4,5,6)]依次取出以下元素:Array[1,1],Array[2,1],,Array[3,1],Array[1,2],Array[2,2],,Array[3,3].
示例
示例如下:
Array <- c(1,2,3,4,5,6)
dim(Array) <- c(2,3) #产生一个2行3列的矩阵
Array
c(Array[1,2],Array[2,3]) #获取第1行第2列数据(为2),第2行第3列数据(为6)
Array[2,] #获取第2行的所有数据
Array[c(1,2,3)] #逐列获取第1,2,3个数据
Array[6]# 逐列获取第6个数据
Array[4]# 逐列获取第4个数据
索引向量
数组可作为索引使用,且数组也是向量,因此作为索引的数组可称为索引向量.示例如下:
- 创建数组x和i,x是被切片的数组,i是索引向量.
x <- array(10:20,dim=c(2,5))
x
i <- array(c(1:3,5:4,3:5),dim=c(2,3)) #1,2,3,5,4,3,4,5,其中,最后的4,5未被列入矩阵
i
2. 以i为索引向量提取数组块,索引向量每个元素代表切片的位置,将这些位置指向的元素提取出来,形成数组块(数组切片).
x[i]
3. 通过索引对数组某个元素赋值.
x[i] <- -111
x
array函数
array函数根据维度参数生成多维数组,它的参数主要有两个,第一个是需要形成数组元素的数据,第二个是dim参数提示维度.
我们演示一个array函数创建数组的方法,并通过dim函数获取数组的大小.示例如下:
h <- c(1:20)
mya <- array(h,dim=c(4,5)) #4行5列
mya
mydim <- c(2,10)
mya <- array(h,dim=mydim)#相当于array(h,dim=c(2,10))
mya
dim(mya) #查看矩阵的行列数
array函数的第一个参数既可以是向量也可以是单个值,示例如下:
mya <- array(1,dim=c(2,10))
mya
数组转换为向量
as.vector函数可以将数组转换为向量,示例如下:
x <- array(c(1:10),dim=c(2,5))
x
matrix矩阵
使用matrix函数可以创建矩阵(从数学角度定义的矩阵),主要参数为:data表示构造所需的数据,nrow为行数,ncol为列数,byrow表示是否按行顺序分配元素(默认:FALSE),示例如下:
matrix(c(1:10),2,5,TRUE)
matrix(c(1:10),2,5)
matrix(c(1:10),2,5,FALSE)
对角矩阵
对角矩阵是一个除主对角线上的元素之外皆为0的矩阵,对角线上的元素可以为0或其他值.
通过diag函数可生成和分析对角矩阵,如果参数为一维数组,则将参数视为对角线元素,并生成对角矩阵,如果参数为一维以上的数组,则将参数视为对角矩阵,对它进行分析,可提取对角线元素,示例如下:
a <- c(1:10)
diag(a) #生成对角矩阵
a <- array(c(1:16),dim=c(4,4))
diag(a) #提取对角线元素
a
数组运算
四则运算
数组的四则运算规律是:对应位置的元素分别计算,而不是依据矩阵的数学运算法则.运算优先级与算术四则运算相同,先乘除后加减.示例如下:
mya <- array(c(1:20),dim=c(2,10))
mya
myb <- array(2,dim=c(2,10))
myb
mya+myb #加法
mya*myb #乘法
3*mya*myb #连乘
mya+mya*myb #先乘除后加减
向量连接
向量连接指的是将两个向量通过某种规律连接成一个数组.R语言的cbind和rbind函数可进行向量连接,其中cbind函数将向量的行转变为列后再进行连接,rbind函数将向量的列转变为行后再进行连接,示例如下:
x2 <- c(101:105)
x1 <- c(1:10)
cbind(x1,x2)
rbind(x1,x2)
矩阵运算
矩阵连接
R语言的cbind函数完成矩阵的横向连接,rbind函数完成矩阵的纵向连接.示例如下:
x3 <- matrix(c(1:10),2,5)
x4 <- matrix(c(101:105),2,5)
x3
x4
cbind(x3,x4)
rbind(x3,x4)
矩阵转置
线性代数将矩阵A的转置(记做
),定义为:
把A的横行写为
的纵列
把A的纵列写为
的横行
根据上述的计算法则,m x n矩阵A的转置生成n x m 矩阵
.
t函数
R语言中的t函数可完成矩阵转置计算,示例如下:
array(1:10,dim=c(2,5)) -> mya
mya
t(mya) #矩阵转置
aperm函数
相对于t函数而言,使用aperm函数进行矩阵转置更灵活.aperm有两个常用的参数.第一个参数是需要转置的矩阵,第二个参数perm指示新矩阵相对于第一个参数矩阵的维度下标.
需要特别注意的是,第二个参数perm是维度下标.比如,将行转换为列,将列转换为行,将行列次序更换,将第一维的元素与第二维的元素互换,则将perm设置成c(2,1),示例如下;
array(1:10,dim=c(2,5)) -> mya
mya
aperm(mya,prem=c(2,1)) -> myb #以c(2,1)为维度下标进行转置
myb
array(mya,c(2,2,5)) -> myc
myc
aperm(myc,perm=c(2,1,3)) -> myd #以c(2,1,3)为维度下标进行转置
myd
aperm(myc,perm=c(1,3,2)) -> myd
myd
结果如下:
> array(1:10,dim=c(2,5)) -> mya
> mya
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
> aperm(mya,prem=c(2,1)) -> myb #以c(2,1)为维度下标进行转置
> myb
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
[4,] 7 8
[5,] 9 10
> array(mya,c(2,2,5)) -> myc
> myc
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
, , 3
[,1] [,2]
[1,] 9 1
[2,] 10 2
, , 4
[,1] [,2]
[1,] 3 5
[2,] 4 6
, , 5
[,1] [,2]
[1,] 7 9
[2,] 8 10
> aperm(myc,perm=c(2,1,3)) -> myd #以c(2,1,3)为维度下标进行转置
> myd
, , 1
[,1] [,2]
[1,] 1 2
[2,] 3 4
, , 2
[,1] [,2]
[1,] 5 6
[2,] 7 8
, , 3
[,1] [,2]
[1,] 9 10
[2,] 1 2
, , 4
[,1] [,2]
[1,] 3 4
[2,] 5 6
, , 5
[,1] [,2]
[1,] 7 8
[2,] 9 10
> aperm(myc,perm=c(1,3,2)) -> myd
> myd
, , 1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 3 7
[2,] 2 6 10 4 8
, , 2
[,1] [,2] [,3] [,4] [,5]
[1,] 3 7 1 5 9
[2,] 4 8 2 6 10
>
矩阵乘积
若A为m x n矩阵,B为n x r矩阵,则它们的乘积AB会是一个m x r的矩阵,前提是m要与n相同,矩阵的乘积使用
%*%
操作符进行计算,示例如下:
array(1:10,dim=c(2,5)) -> a
a
array(1:10,dim=c(5,2)) -> b
b
a %*% b #矩阵乘积计算
内外积运算
向量外积
向量外积是矩阵的克罗内克积的特殊情况,给定m x 1 列向量 u 和1 x n 行向量v,它们的外积u
v被定义为m x n 矩阵A.
向量外积u
v的计算定义为:
![]()
下面的示例演示了a和b数组作为向量的外积运算
%o%
和普通乘法运算:
a <- array(c(1:4))
a
b <- array(c(5:8))
b
a%o%b #外积
b%o%a #外积
a*b #普通乘法
b*a #普通乘法
此外,可以使用
Quter(a,b,"*")
代替%o%
运算进行外积运算
向量内积
向量内积以实数R上定义的两个向量为运算对象,返回一个实数标量值,属于二元运算,它是欧几里得空间的标准内积.
两个向量
和
的内积定义为:
R语言通过crossprod函数完成向量内积运算,示例如下:
a <- c(1:3)
b <- c(4:6)
crossprod(a,b)
矩阵内积
矩阵内积的计算方式相当于第一个参数的转置乘以第二个参数,就是前面提到的矩阵乘积,除了使用
%*%
操作符以外,还可以使用crossprod函数完成矩阵的内积运算,示例如下:
a <- array(c(1,3),dim=c(1,3))
a
b <- array(c(4,6),dim=c(1,3))
b
crossprod(a,b) #a与b完成矩阵内积计算
t(a) %*% b #a的转置与b完成矩阵内积计算
求解线性方程组
一般通过solve函数来求解
a %*% x = b
中的x向量值,求解线性方程组仅使用solve函数的前两个参数,第一个a为系数矩阵,第二个b为常数项,当b缺失时,默认为单位矩阵,示例如下:
a <- array(1:4,dim=c(2,2))
a
b <- array(8:9,dim=c(2,1))
b
solve(a,b)
矩阵求逆
通过solve函数可进行矩阵求逆运算,只指定一个参数(待求逆的矩阵)即可,示例如下:
a <- array(1:4,dim=c(2,2))
a
solve(a)
矩阵的特征值求解
概念
λ是A的特征值等价于线性系统(A-λI )v = 0(其中I 是单位矩阵)有非零解v(一个特征向量),特征值存在等价于下面的行列式成立:
函数
(λ)=det(A-λI )是一个关于λ的多项式,称为A的特征多项式.矩阵的特征值也就是其特征多项式的零点.
求一个矩阵A的特征值可以通过求解方程
(λ)=0得到.
求解
使用R语言的eigrn函数可求解特征值,调用格式如下:
eigen(x,symmetric,only.values = FALSE)
x是需要求特征值得矩阵,symmertic是逻辑型,表示是否为对称矩阵,对称矩阵是一个方形矩阵,其转置和自身相等,即A=
,对称矩阵A=(
)从右上至坐下方向的元素以主对角线(左上到右下)为轴对称,即
=
.
only.values
如果为TRUE
,则只返回特征值,否则返回特征值和特征向量.下面的示例演示了eigen函数计算特征值的方法.
a <- array(c(1:16),dim=c(4,4))
eigen(a) #计算a的特征值
eigen(a,only.values=FALSE)#计算a的特征值和特征向量
求解矩阵行列式
行列式是线性代数中的一个概念,将 n x n 的矩阵A映射到一个标量,记做det(A)或者|A|.行列式可看作是有向面积的一个概念在一般的欧几里得空间中的推广.
比如, 假设矩阵A定义为:
则矩阵A的行列式|A|可定义为
R语言的det函数可求解矩阵对应的行列式值,即:已知矩阵A,求|A|,示例如下:
a <- array(c(1:4),dim=c(2,2))
det(a)
奇异分解
奇异矩阵分解是线性代数中的一种重要的矩阵分解,在信号处理,统计学等领域有重要的应用.
假设M是一个m x n阶矩阵,其中的元素全部属于域K(实数域或复数域).设存在一个分解使得:
M=U∑V*
其中U是m x m 阶酉矩阵,∑是半正定m x n 阶对角矩阵,V*(即V的共轭转置)是n x n 阶酉矩阵.
这种分解称作M的奇异值分解,∑对角线上的元素
即为M的奇异值.
使用R语言的svd函数可完成奇异分解,示例如下:
a <- array(c(1:16),dim=c(4,4))
a
svd(a) #奇异分解