海林老師《數據挖掘》(韓佳煒書)課程作業系列
要求:自己寫R/Python代碼、函數實現一系列算法
其他參見:
全文邏輯:
- 分析
- 算法/函數
- 測試數據
- 測試代碼
- 測試結果(截圖)
分析:基於書上的僞代碼
##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聚類結果")
測試結果: