数据挖掘实验(八):DBSCAN聚类 R语言

一、 实验目的

  1. 了解DBSCAN算法基本原理;
  2. 编写代码并实现DBSCAN算法对数据的聚簇

二、 实验步骤

  1. 采用的数据集 :R语言factoextra包里的multishapes数据集
    在这里插入图片描述
  2. 函数首先确定两个参数:
    (1)epsilon:在一个点周围邻近区域的半径
    (2)minPts:邻近区域内至少包含点的个数
    根据以上两个参数,可以把样本中的点分成三类:

核点:满足领域内的点>=minPts,则为核样本点
边界点:满足领域内的点<minPts,但是该点可由一些核点获得
噪声点:既不是核点也不是边缘点,则是不属于这一类的点

  • 用欧式距离计算点与点之间的距离矩阵disMatrix
  • 为数据集添加visited列,0表示未访问,1表示访问过
  • 判断点的类型存放到data_N
  • 删除噪声点存放到data_C
  • 重新计算距离,合并有交集的领域
  • 为不同类型的点标签
  • 绘图

三、 实验代码

library(factoextra)
library(ggplot2)

data<-data.frame(multishapes[,1:2])

ggplot(data,aes(x,y))+geom_point()

#主函数
DBSCAN = function(data,eps,MinPts){

rows = nrow(data)
disMatrix<-as.matrix(dist(data, method = "euclidean"))#求距离

data$visited <- rep(0,rows)
names(data)<-c("x","y","visited")

data_N = data.frame(matrix(NA,nrow =rows,ncol=3)) #领域集N,存放索引、领域内的点数、点的类型
names(data_N)<-c("index","pts","cluster")
 
#判断点的类型,1核心点,2边界点,0噪声点

for(i in 1:rows){
  if(data$visited[i] == 0){ #未被访问的点
    data$visited[i] = 1  #标记已经被访问
    index <- which( disMatrix[i,] <= eps)
    pts <- length(index)
     
   
     if(pts >= MinPts){
      data_N[i,]<-c(i,pts,"1")
    }else if(pts>1 && pts< MinPts){
      data_N[i,]<-c(i,pts,"2")
    }else{
      data_N[i,]<-c(i,pts,"0")
    }
  }
}

   #删除噪声点
  data_C<-data[which(data_N$cluster!=0),]
  
  #去掉噪声点之后的领域
  disMatrix2<-as.matrix(dist(data_C, method = "euclidean"))
  Cluster<-list()
  for(i in 1:nrow(data_C)){
    Cluster[[i]]<-names(which(disMatrix2[i,]<= eps))
  }
  
#合并有交集的邻域,生成一个新簇

  for(i in 1:length(Cluster)){
    for(j in 1:length(Cluster)){
      if(i!=j && any(Cluster[[j]] %in% Cluster[[i]])){
        if(data_N[Cluster[[i]][1],]$cluster=="1"){
          Cluster[[i]]<-unique(append(Cluster[[i]],Cluster[[j]])) #合并,删除重复
          Cluster[[j]]<-list()
        }
      }
    }
  }

  newCluster<-list()       #去掉空列表
  for(i in 1:length(Cluster)){
    if(length(Cluster[[i]])>0){
      newCluster[[length(newCluster)+1]]<-Cluster[[i]]
    }
  }
  
  #为相同簇中的对象赋相同的标签

  
  data_C[,4]<-as.character()
  for(i in 1:length(newCluster)){
    for(j in 1:length(newCluster[[i]])){
      data_C[newCluster[[i]][j],4]<-i
    }
    
  }
  return(data_C)
}


  
  
  #运行
test<-DBSCAN(data,0.15,6)  #设定eps为0.15,minpts为6


ggplot(test,aes(x,y,colour=factor(test[,4])))+
  geom_point(shape=factor(test[,4]))

四、 运行结果

原数据
在这里插入图片描述
经过聚类后
在这里插入图片描述

发布了11 篇原创文章 · 获赞 0 · 访问量 63

猜你喜欢

转载自blog.csdn.net/qq_43863790/article/details/104069549
今日推荐