海林老师《数据挖掘》(韩佳炜书)课程作业系列
要求:自己写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聚类结果")
测试结果: