今天聊聊k均值聚类分析,我们先要知道什么是类,在大数据时代,我们每个人都被打上很多个性标签,比如:宅男,月光族,手机控,非主流等等,每个标签都可以算是一个类,因此,可以不严谨的说:类是一些有特殊属性个体的集合。而聚类分析的目的,就是要把这些个人找出来并区别出来,聚类分析属于无监督机器学习的一个重要内容,今天我们来聊聊K均值聚类分析,那么k均值聚类分析和之前的层级聚类分析有什么不同呢?
K-Means算法是发展最成熟且原理简单、算法流程清晰,经典算法的步骤描述,分为如下5步完成。
①随机选取K个样本作为n个样本点类中心center_K;
②计算各样本点plot (x[i], y[i])与各类中心cen⁃ter_K的距离;
③将各样本归于最近的类中心点;
④求各类的样本的均值,作为新的类的中心center_K_new;
⑤判定:若类中心不再发生变动或达到迭代次数,算法结束,否则回到第②步。

如图下图所示: 在图中一共有a至e这5个数据以及2个随机的质心点(灰色点)。图

3(a)为算法经过初始化后的状态, 图3(b)和图3(d)是两个更新过程, 图3©和图3(e)是两个更新后的状态。经过2轮更新该算法达到稳定如图3(e)所示。

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_聚类分析


我们继续使用之前的肉类数据(关注公众号回复:肉类数据可以获得该数据)来进行k均值聚类分析,需要factoextra,dplyr,pacman,cluster包,需要事先下载好,我们先导入数据和包

library(factoextra)
library(dplyr)
library(pacman)
library(cluster)
bc<-read.csv("E:/r/test/roulei.csv",sep=',',header=TRUE)
names(bc)

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_聚类分析_02


数据有5个参数,energy代表食物能量(卡路里),protein蛋白质,fat脂肪,calcium钙含量,iron铁含量,竖排是各种肉的名字,我就不一一解释了。

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_数据_03


数据的变量差别很大,我们首先要把数据标准化,然后计算欧式距离

bc.scaled<-scale(bc[2:6])##标准化数据
d<-dist(bc.scaled)###计算欧氏距离

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_聚类分析_04


在K均值聚类分析中, K的个数(即分成几类)这个参数非常重要,我们先用NbClust的投票功能来看看

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_数据_05


这里显示2,3类都有4次投票,即分层2类和3类都是可以的。

我们还可以使用cluster函数做增强k均值聚类分析,可以自己聚类,自动分类,在这里函数倾向于分成2类

km <- eclust(bc[2:6], "kmeans", nstart = 25) #聚类的散点图

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_bc_06


也可以通过fviz_gap_stat函数来投票

fviz_gap_stat(km$gap_stat) # 不同K值下Gap 统计图,指导选择最佳K值
fviz_silhouette(km) # 轮廓图,每种聚类下面的分布情况

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_bc_07


函数fviz_gap_stat也倾向分成2类

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_bc_08


r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_数据_09


那么问题来了,我们到底应该分成2类还是3类呢,我们可以根据我们的临床需要进行判断,我们可以先把图都做出来比较一下

2类的

set.seed(666)
kmeans1<-kmeans(bc.scaled,centers=2,nstart = 25)
fviz_cluster(object=kmeans1,data=bc[2:6],
             ellipse.type = "euclid",star.plot=T,repel=T,
             geom = ("point"),palette='jco',main="",
             ggtheme=theme_minimal())+
  theme(axis.title = element_blank())

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_bc_10


3类的

kmeans1<-kmeans(bc.scaled,centers=3,nstart = 25)
fviz_cluster(object=kmeans1,data=bc[2:6],
             ellipse.type = "euclid",star.plot=T,repel=T,
             geom = ("point"),palette='jco',main="",
             ggtheme=theme_minimal())+
  theme(axis.title = element_blank())

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_bc_11

我们可以见到,分成3类后的第1类(红色箭头部分)虽然数据很少,但是离第3类还是很远的,我个人觉得不应该被归入第一类(个人看法),我们就先按3类来分看看。

summary(kmeans1)
kmeans1$cluster
kmeans1$size

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_数据_12


上图可以看到,各种肉类被分进了组,第一组2种,第二组9种,第三组16种

我们把数据集整理一下,如下图,数据被我们分类整理了

aaa <- data.frame(bc[2:6], kmeans1$cluster)
aaa<-arrange(aaa,kmeans1.cluster)

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_聚类分析_13


我们对每组的数据进行平均值统计

by_fenzu<-group_by(aaa,kmeans1.cluster)
summarize(by_fenzu,energy=mean(energy),protein=mean(protein),
          fat=mean(fat),calcium=mean(calcium),iron=mean(iron))

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_聚类分析_14


由上图我们可以得出每组数据的各类指标平均数,因此我们可知,第一种肉类含能量少,蛋白质少,脂肪少,属于没有什么营养的肉类。第二种肉类:能量很多,脂肪也很多,可以参考为油炸的高脂肪垃圾食品。第三种为:低热量,高蛋白质,低脂肪,并且富含钙的肉类,比较适合我们中国人的饮食理念和习惯。这样得出的结论可以在饮食上给出建议。

我们还可以得出每组指标的密度分布情况:

先对数据分组

Data1 <- aaa[which(aaa$kmeans1.cluster == 1), ]
Data2 <- aaa[which(aaa$kmeans1.cluster == 2), ]
Data3 <- aaa[which(aaa$kmeans1.cluster == 3), ]

做能量的分布曲线

par(mfrow = c(1,3))
plot(density(Data1[, 1]), col = "red", main = "1.energy")
plot(density(Data2[, 1]), col = "red", main = "2.energy")
plot(density(Data3[, 1]), col = "red", main = "3.energy")

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_聚类分析_15


脂肪的分布曲线

par(mfrow = c(1,3))
plot(density(Data1[, 3]), col = "red", main = "1.fat")
plot(density(Data2[, 3]), col = "red", main = "2.fat")
plot(density(Data3[, 3]), col = "red", main = "3.fat")

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_数据_16


其他的指标也可以同理做出来,这里就不一一演示了

我们还可以通过散点图矩阵,将每组的数据关系表示出来,并且以不同颜色区分

pairs(energy~protein+fat+calcium,data = aaa,pch = 21,
      bg = c("red", "green3", "blue")[unclass(aaa$kmeans1.cluster)])

r语言ggplot绘制K均值聚类结果 k均值聚类 r语言_bc_17