R-数据挖掘-聚类DBSCAN(七)

海林老师《数据挖掘》(韩佳炜书)课程作业系列

要求:自己写R/Python代码、函数实现一系列算法

其他参见:

R-数据挖掘-求混合型数据对象距离(一)

R-数据挖掘-主成分分析PCA(二)

R-数据挖掘-关联规则(三)

R-数据挖掘-决策树ID3(四)

R-数据挖掘-贝叶斯分类(五)

R-数据挖掘-聚类Kmeans(六)

R-数据挖掘-聚类DBSCAN(七)

全文逻辑:

  1. 分析
  2. 算法/函数
  3. 测试数据
  4. 测试代码
  5. 测试结果(截图)

分析:基于书上的伪代码

##data对象,二维点(x,y)
##eps半径
##MinPts最小数目
####返回每个对象所属的类标签(数值向量)

 

算法实现(编写函数):

mydbscan<-function(data,eps,MinPts){
  #求欧式距离矩阵
  d = as.matrix(dist(data))
  #创建向量visited记录是否访问
  visited=rep(0,nrow(data))
  #创建簇的集合
  cu=list(NULL)
  i=0
  while(length(which(visited==0))>0){
    #找出所有未访问的对象
    index=which(visited==0)
    #随机取一个对象(在此取第一个对象p)
    p=index[1]
    #标记P已访问
    visited[p]=1
    #根据距离矩阵判断 满足最小半径的同时是否满足最小数目
    if (length(which(d[p,]<eps))>MinPts){
      i=i+1
      #创建新簇cu
      cu[[i]]=c(p)
      #取出P的邻域N
      N=which(d[p,]<eps)
      #遍历N(N是不断扩大的),只能用while
      k=0
      while(length(N)>k){
        k=k+1
        j=N[k]
        if(visited[j]!=1){
          visited[j]=1
          if(length(which(d[j,]<eps))>MinPts){
            #获取J邻域序号,扩充N
            j_index=which(d[j,]<eps)
            N=unique(c(N,j_index))
          }
          #若j未加入cu则加进去
          #if(!(j%in%cu[[i]])){
            cu[[i]]=unique(c(cu[[i]],j))
         # }
        }
      }
      
    }else{
      visited[p]=2#p为噪声数据
    }
  }
  #返回列表result
  ##clusters:每个对象所属类标签
  result=rep(0,nrow(data))
  for (cui in 1:length(cu)) {
    result[(cu[[cui]])]=cui
  }
  return(result)
}

 

数据测试:

测试数据:

有趣的数据

x1 <- seq(0,pi,length.out=100)
y1 <- sin(x1) + 0.1*rnorm(100)
x2 <- 1.5+ seq(0,pi,length.out=100)
y2 <- cos(x2) + 0.1*rnorm(100)
data <- data.frame(c(x1,x2),c(y1,y2))
names(data) <- c('x','y')
a=mydbscan(data,0.2,4)
library(ggplot2)
ggplot(data,aes(x,y))+geom_point()+
  labs(title="原数据展示")
p<-ggplot(data,aes(x,y))
p + geom_point(size=2.5, aes(colour=factor(a)))+
  labs(title="dbscan聚类结果")

 

测试结果:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章