机器学习第4章第3节 : R语言计算实例
学生数据集读写
list方法
R语言可以使用list(列表)组件创建与读写学生数据,该组件通常用来容纳一个数据集其中包含不同的数据类型.
- 创建学生数据集(语法:
list(字段1 = 组件1 , 字段2 = 组件2,......)
),学生数据集由3个不同的类型的数据组成:name
,class
,ages
,代码如下:
list(name = "student",class = "101",students.ages = c(22,25,20),students.name = c("zhangsan","lisi","wangwu")) -> mystudents
- 读取列表,去读刚才创建的学生数据集,代码如下:
mystudents
执行结果:
> mystudents
$name
[1] "student"
$class
[1] "101"
$students.ages
[1] 2225 20
$students.name
[1] "zhangsan" "lisi" "wangwu"
- 获取学生数据集的字段总数(通过length返回list组件的数量),代码如下:
length(mystudents)
执行结果:
> length(mystudents)
[1] 4
- 查看数据集中所有学生的姓名和年龄(通过”
列表变量名$字段名
“提取组件内容)代码如下:
c(mystudents$students.name , mystudents$students.ages)
执行结果:
> c(mystudents$students.name , mystudents$students.ages)
[1] "zhangsan" "lisi" "wangwu" "22" "25" "20"
data.frame方法
此外,R语言还提供了一个很不错的list组件
data.frame
,它内部可拥有很多组件.
- 创建data.frame组件存储学生数据,代码如下:
data.frame(name = mystudents$students.name , age = mystudents$students.ages) -> mysts
- 将数据集中的年龄都增长1岁(类似于新的一年大家都长大了一岁),可使用
attach
和detach
方法
前面一直在使用$符号访问list里面的内容,当R语言的代码较多时,列表组件名前缀访问字段很不方便,因此,R语言提供了另一对非常有用的工具
attach
和detach
.attach是把数据集的所有字段复制一份副本绑定在所有路径,这样可以直接读取它们(仅仅是读取,写是写在副本上的,写在副本上是没有意义的),无需显示表明列表名字
detach是解绑.
用attach将学生数据集的字段副本绑定在所有路径中,代码如下:
attach(mysts)
age
name
执行结果:
> attach(mysts)
> age
[1] 22 25 20
> name
[1] zhangsan lisi wangwu
Levels: lisi wangwu zhangsan
>
将绑定的age字段副本加1,并显示更新后的学生数据,代码如下:
age+1 -> mysts$age
mysts
执行结果:
> age+1 -> mysts$age
> mysts
name age
1 zhangsan 23
2 lisi 26
3 wangwu 21
使用detach将字段副本从搜索路径上删除(解绑),代码如下:
detach(mysts)
age
name
执行结果:
> detach(mysts)
> age
错误: 找不到对象'age'
> name
错误: 找不到对象'name'
最小二乘法拟合
最小二乘法与回归
最小二乘法是一种数学优化技术,它通过最小化误差的平方和找到一组数据的最佳函数匹配.
假设存在(x,y)两个变量,对于一系列的x变量值,有一系列的y值与其对应,可以找到这两个变量之间的相互关系.比如,对于一次函数来说,可将这些(x,y)值标注在直角坐标系统,从而得到一条直线,这些点就在这条直线附近,那么,直线返程的定义为:
y=kx+b
其中,k和b是任意实数,k为斜率,b为截距.
我们以
y=3x+12
和y=6x+12
为例进行分析.如下图
从上图我们可以很直观的看出,斜率越大,直线越陡(蓝线k值为6,黄线k值为3,蓝线比黄线陡),无论哪条线,对于每一个x,都有一个y值都相对应,比如,当x为1.5时,我们想要求黄线上的坐标,可直接将x=1.5代入y=3x+12就可以得到:
y=3 x 1.5 + 12 = 16.5
这样我们就可以使用 y=kx+b形式的一次方程拟合数据点,这个过程称为线性拟合,拟合的目标是这些点到这条直线的距离的平方和最小(比如刚才的(x=1.5,y=16.5),它到直线y=3x+12的距离的平方和为0,达到了最小).最小二乘法是效果较好的线性拟合的方法,最小二乘法拟合数据点的的过程就是对数据做回归分析,我们把类似上图的几条直线称为回归线
最小二乘法拟合
R语言提供了
lsift
函数,可完成小二乘法拟合,其主要参数如下:
x | y | Wt | Intercept | Tolerance | Yname |
---|---|---|---|---|---|
一个矩阵的行对应的情况和其列对应为变量 | 结果,可以是一个矩阵 | 可选参数,加权最小二乘法的执行权重向量 | 是否使用截距项 | 公差将用于矩阵分解 | 用于响应变量的名称 |
我们来看看y=2x回归方程拟合,这里以x=(1,2,3,4),y=(2,4,6,8)为例在R中进行数据拟合,代码如下:
x <- c(1,2,3,4)
y <- c(2,4,6,8)
lsfit(x,y) #下面的执行结果中x为常数项,Intercept为截距
执行结果:
> x <- c(1,2,3,4)
> y <- c(2,4,6,8)
> lsfit(x,y) #下面的执行结果中x为常数项,Intercept为截距
$coefficients
Intercept X
0 2
#----------------------------#
#.....删去了不必要的的结果代码.....#
在上面的拟合结果中,Intercept代表截距,x表示方程的x变量的常数项,因此,回归方程为y=2x+0=2x
再看看y=2x+3的回归方程拟合,设截距为3,修改刚才的方程,假设回归线为: y=2x+3
根据回归线构造x和y,执行lsfit()函数进行拟合,代码如下:
x <- c(1,2,3,4)
y <- c(5,7,9,11)
lsfit(x,y)
执行结果:
> x <- c(1,2,3,4)
> y <- c(5,7,9,11)
> lsfit(x,y)
$coefficients
Intercept X
3 2
#----------------------------#
#.....删去了不必要的的结果代码.....#
根据结果,这些数据点的回归方程为y=2x+3
交叉因子频率分析
交叉因子频率分析的作用在于分析数据的分布区间及其统计指标.
- 划分数据分布区间.使用cut()函数将变量y中存储的数字划分到5个分布区间,代码如下:
y <- c(11,22,13,14,11,22,31,31,31,14)
cuty <- cut(y,5)
cuty
执行结果:
> y <- c(11,22,13,14,11,22,31,31,31,14)
> cuty <- cut(y,5)
> cuty
[1] (11,15] (19,23] (11,15] (11,15] (11,15] (19,23] (27,31] (27,31] (27,31] (11,15]
Levels: (11,15] (15,19] (19,23] (23,27] (27,31]
- 使用table函数统计数据再每个区间出现的频率,代码如下:
table(cuty)
执行结果:
> table(cuty)
cuty
(11,15] (15,19] (19,23] (23,27] (27,31]
5 0 2 0 3
- 使用hist函数生成分布直方图,以便更直观的观察数据分布情况.通过指定
breaks
参数(设置为各区间的边界值)和axes
参数(设置为FALSE表示手动画刻度),将数据再table函数生成的区间内进行划分,代码如下:
bins <- seq(min(y),max(y),by=4)
hist(y,breaks=bins,col="lightblue",axes=FALSE)
axis(1,bins)
axis(2)
如果没有弹出图形界面,就在R界面中选择
窗口-2 R Graphics:Device:2 (ACTIVE)
,结果如下图:
结合table函数执行的结果以及hist函数 生成的直方图,可以都得到以下结论:
分析table函数的执行结果可以看出,数据主要都击中在[11,15]的区间中,[11,15]的区间内分布的数字最多,该区间有5个数字.此外在[15,19]和[23,27]区间中没有数据分布,变量y在这两个区间内出现的频率为0.
从上图可以看到,数据分布情况与table函数的执行结果相吻合.
向量模长计算
向量模长即欧几里得范数,在n 维欧几里得空间Rn上,向量的长度定义为.
根据勾股定理,它给出了原点到点x之间的距离.
模长函数定义
R拥有自定义函数功能可按如下格式定义:
yourFunctionName <- function(parameter1,parameter2,parameter3,......,parameterN){
#your code#
}
下面定义一个三维向量模长的
vector_length
函数,完成模长计算
vector_length <- function(x1,x2,x3){
vlength <- sqrt(x1^2 + x2^2 + x3^2)
vlength
}
模长计算
调用
vector_length
函数,计算向量[12,22,19]的模长
vector_length(12,33,19)
执行结果:
> vector_length(12,33,19)
[1] 39.92493
N维向量的模长与三维模长类似,我们重新定义 vector_length函数,并调用它计算任意维度向量的模长,代码如下:
# 定义vector_length函数
vector_length <- function(x){
temp <- 0
for (i in 1:length(x)){
temp <- temp + x[i]^2
}
vlength <- sqrt(temp)
vlength #打印出结果
}
# 调用vector_length计算任意维度的向量模长
vector_length(c(11,22,33,44,55))
vector_length(c(11,22,33,44,55,66,77,88,99))
执行结果
> # 定义vector_length函数
> vector_length <- function(x){
+ temp <- 0
+ for (i in 1:length(x)){
+ temp <- temp + x[i]^2
+ }
+ vlength <- sqrt(temp)
+ vlength #打印出结果
+ }
>
> # 调用vector_length计算任意维度的向量模长
> vector_length(c(11,22,33,44,55))
[1] 81.57818
> vector_length(c(11,22,33,44,55,66,77,88,99))
[1] 185.7014
欧式距离计算
欧氏距离(Edclid Distance)是在n维空间中两个点的真实距离.n维欧式空间的每个点都可以表示为(x[1],x[2],x[3],……,x[n]), X=(x[1],x[2],x[3],……,x[n])和Y=(y[1],y[2],y[3],……,y[n]),这两个点之间的距离d(X,Y)定义为以下公式:
利用R语言的操作符自定义功能完成欧式距离计算,操作符的定义使用
%符号%
的方式定义实际使用时,%特属于操作符的一部分,操作符的定义格式如下:
操作符名 <- function(参数1,参数2,参数3,......,参数n){
语句
}
下面定义
%~%
操作符,并计算二维空间的欧氏距离,代码如下:
"%~%" <- function(x1,x2){
temp <- 0
for(i in 1:length(x1)){
temp <- (x1[i] - x2[i])^2
}
edis <- sqrt(temp)
edis
}
#使用%~%操作符,计算二维空间的欧式距离
c(1,2,3) %~% c(4,5,6)
计算结果:
> "%~%" <- function(x1,x2){
+ temp <- 0
+ for(i in 1:length(x1)){
+ temp <- (x1[i] - x2[i])^2
+ }
+ edis <- sqrt(temp)
+ edis
+ }
>
> #使用%~%操作符,计算二维空间的欧式距离
> c(1,2,3) %~% c(4,5,6)
[1] 3
可以将计算扩展到n维空间中.使用R语言的不定数量参数的机制,来定义n维空间的欧式距离函数mycount,代码如下:
mycount <- function(...){
temp <- 0
for (i in c(...)){
temp = temp +1
}
temp
}
mycount(11,22,33)
mycount(22,33,44,55)
mycount(11,55,99)
执行结果:
> mycount <- function(...){
+ temp <- 0
+ for (i in c(...)){
+ temp = temp +1
+ }
+ temp
+ }
>
> mycount(11,22,33)
[1] 3
> mycount(22,33,44,55)
[1] 4
> mycount(11,55,99)
[1] 3