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聚類結果")

 

測試結果:

 

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