本次为学生时期所写的实验报告,代码程序为课堂学习和自学,对网络程序有所参考,如有雷同,望指出出处,谢谢!
基础知识来自教材:李航的《统计学习方法》
本人小白,仍在不断学习中,有错误的地方恳请大佬指出,谢谢!
一、层次聚类代码
1.前置预备函数
##############1:计算类与类之间的欧式距离##########
my_dist<-function(X,Y,p){
#X,Y为两个类,p为变量的维数
X=matrix(X,ncol=p)
Y=matrix(Y,ncol=p)
n1=nrow(X)
n2=nrow(Y)
if(n1==1&n2==1){ #两向量距离
d=sqrt((X-Y)%*%t(X-Y))
}else if(n1!=1&n2==1){ #单个向量到类(多个向量)之间的距离(最短距离法)
d=min(as.matrix(dist(rbind(Y,X)))[-1,1])
}else if(n1==1&n2!=1){
d=min(as.matrix(dist(rbind(X,Y)))[-1,1])
}else if(n1!=1&n2!=1){ #类(多向量)到类(多向量)之间的距离(最短距离法)
d=min(as.matrix(dist(rbind(X,Y)))[-c(1:n1),1:n1])
}
d
}
##############2:寻找指定数据在原始数据矩阵中的位置##########
index_find<-function(X,data,p){ #data为给定的数据
data=matrix(data,ncol=p)
n=nrow(data)
index=0
for (j in 1:nrow(data)) {
for (k in 1:nrow(X)) {
TF=as.numeric(data[j,]==X[k,])
if(sum(TF)==p){
index=append(index,k)
}
}
}
index=index[-1]
}
##############3:为保证不出现分支,确定数据在聚类图中的特定排序#########
order_find<-function(indexlist,n){
order=0
#基本思想:从后往前,提取每一次聚类的两个类中含有数据较少的那个类中的数据
for (k in length(indexlist):1) {
nk=rep(NA,length(indexlist[[k]]))
for (m in 1:length(indexlist[[k]])) {
nk[m]=length(indexlist[[k]][[m]])
}
TF=as.numeric(nk==c(1,1))
if(sum(TF)!=2){
order=append(order,indexlist[[k]][[which.min(nk)]])
}else if(sum(TF)==2){
order=append(order,indexlist[[k]][[1]])
order=append(order,indexlist[[k]][[2]])
}
if(length(order)==n+1){
order=order[-1]
break
}
}
order
}
2.层次聚类代码编写
############编写层次聚类函数#####
my_clust<-function(X){ #使用最短距离法
X=as.matrix(X) #X转化为矩阵,便于后续计算
n=dim(X)[1] #n为样本数
p=dim(X)[2] #p为向量维数
C_all=matrix(1:n,byrow=TRUE,nrow = n,ncol = n)
#每一行记录每一次聚类后各向量对应的类别
distance_record=rep(0,n-1) #记录聚类时的最短距离
merge=matrix(NA,ncol = 2,nrow = n-1)
#merge记录聚类情况:每一行表示一次聚类(概念设定与hclust输出模型中的“merge”相同):
#两负数表示两个单向量聚为一类,
#一正一负表示负的那个单向量聚到正的数值所在的类
#两正则表示两个大类聚合为一类
indexlist<-list() #记录每一次聚的两个类的标签
#初始距离矩阵
D_dist=matrix(0,nrow = n,ncol = n)
D_dist[1:n,1:n] = as.matrix(dist(X)) #转化为矩阵格式(此时为对角矩阵且对角线元素为0)
D_dist[D_dist==0]=round(max(D_dist))+1 #将0全部转化为最大值
#返回距离最小的两个类
index=unique(which(D_dist[1:n,1:n]==min(D_dist[1:n,1:n])
arr.ind=TRUE)[1,])
#第一次聚类:两个单向量聚为一类:故merge第一行为两负数
merge[1,]=-index
#记录距离最小值
distance_record[1]=min(D_dist[1:n,1:n])
#给新类加上标签
for (m in 1:length(index)) {
C_all[2:n,which(C_all[1,]==index[m])]=n+1
}
#开始迭代层次聚类
i=2
while (i<=n) {
#各自把X属于同一类的提取出来
dataselected=split(X, C_all[i,],drop = FALSE)
classnum=length(dataselected) #记录此时类别数
D_dist=matrix(0,nrow = classnum,ncol = classnum)
#计算各类