R语言数据可视化_科学统计图表3——ggplot绘制层次聚类图
层次聚类图相信大家都很了解了,但是我们往往只能够画一个十分朴素的层次聚类图,像这样的…
或许我们可以在这张图上稍作修改,但也仅限于在某个高度加条红线,这就造成了读图的困难。这个问题之所以困扰我们,是因为并不是所有的绘图函数都如ggplot一样充满艺术性且有非常多的受众(便于我们查找和学习)。就算某个根据ggplot开发的包能够绘制层次聚类图,它也不像ggplot那样能够任由我们天马行空的想象对图自由地进行修改。
所以我(趾高气昂),今天!用ggplot写了个层次聚类,为广大学子带来了福音(掌声)!我并没有打算把它封装成一个包或函数,因为这样做相当于抛弃了ggplot的自由性和艺术性,所以本片文章我会从数据开始,一步步的解释我的代码。
library("factoextra")
data(USArrests)
#这次所用的数据
df <- scale(USArrests)
#标准化一下
result <- dist(df, method = "euclidean")
result_hc <- hclust(d = result, method = "ward.D2")
#获得层次聚类的结果result_hc
fviz_dend(result_hc, cex = 0.6)
#画个层次聚类图看看
然后我们用ggplot重写下
我的绘制思想是利用geom_line画出图中的每一个杠(如下图),每一个杠由四个点顺序链接所构成,所以代码主要就是在找每个杠对应的四个点,并用group将他们分开。
len = dim(USArrests)[1]
#这里定义了数据的数量
#######################################################
################危 从这里开始 危####################
#######################################################
ranks = c(1:(2*len-1))
for (i in c(1:len)) {
ranks[i] = which(result_hc$order==i)
}
ranks[(len+1):(len+2)] = 0
for (i in 1:(len-1)) {
rank1 = 0
rank2 = 0
if(result_hc$merge[i,1]<0)
{
rank1 = ranks[-result_hc$merge[i,1]]
}else{
rank1 = ranks[result_hc$merge[i,1]+len]
}
if(result_hc$merge[i,2]<0)
{
rank2 = ranks[-result_hc$merge[i,2]]
}else{
rank2 = ranks[result_hc$merge[i,2]+len]
}
ranks[i+len] = (rank1 + rank2)/2
}
ranks
x = c(1:4*(len-1))
y = c(1:4*(len-1))
heigh = c(1:(2*len -1))
heigh[1:len] = 0
heigh[(len+1):(2*len -1)] = result_hc$height
merge_ = result_hc$merge
for (i in 1:(2*(len-1))) {
if(result_hc$merge[i]>0)
{
merge_[i] = result_hc$merge[i]+len
}else{
merge_[i] = -result_hc$merge[i]
}
}
for (i in 1:(len-1)) {
index = (i-1)*4 + 1
x[index] = ranks[merge_[i,1]]
y[index] = heigh[merge_[i,1]]
x[index+1] = ranks[merge_[i,1]]
y[index+1] = result_hc$height[i]
x[index+2] = ranks[merge_[i,2]]
y[index+2] = result_hc$height[i]
x[index+3] = ranks[merge_[i,2]]
y[index+3] = heigh[merge_[i,2]]
}
#######################################################
################危 到这里结束 危####################
#######################################################
#都不用看!
#复制粘贴就可以
########################################################
data = data.frame(x=x,y=y,group = rep(1:(len-1),each=4))
#这个data是绘制图像所用数据,也是上面那段代码的全部成果
ggplot(data,aes(x=x,y=y,group=group ))+geom_line()
#绘制完成~
看下data
这里group由低到高分别对应了聚类分析的每次聚类结果,比如说最大的组——group49就对应了图中最高的那个杠…
好嘞,看下ggplot能实现什么样的想法吧!