数据挖掘-层次聚类与K均值算法的R实现

本次为学生时期所写的实验报告,代码程序为课堂学习和自学,对网络程序有所参考,如有雷同,望指出出处,谢谢!

基础知识来自教材:李航的《统计学习方法》

本人小白,仍在不断学习中,有错误的地方恳请大佬指出,谢谢!

一、层次聚类代码

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)
    
    #计算各类
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值