在前面的文章中讲过数据离散化和KMeans算法的理论理解。

参见:数据离散化及其KMeans算法实现的理解

这篇文章来看看怎样用Python实现这个事。



Python聚类的方法_python聚类

K-Means的步骤



01 目标

有下图所示的一系列数据,总共有900多条,这是《Python数据分析与挖掘实战》这本书第4章的案例数据。




Python聚类的方法_python聚类_02


从图中可见,测量值非常多,但实际上肝气郁结要么就是有要么就是没有,就两种情况;再细致一点,我们可能分成好、不太好、差、很差四类。当然,具体怎样分法需要这方面的专业人士来定。

反正,就拿过来这样一堆数据,根据这组数据情况呢把病人给分成四类。

也就是说,我们的目标就是将这900多条数据用K-Means算法给分成4类。

02 实现步骤

Step1,当然是把需要用到的第三方库给import进来

import pandas as pdimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeans

KMeans就是要用到第三行。

Step2,当然是把数据读到pandas的dataframe中

datafile = u'../data/discretization_data.xls'data = pd.read_excel(datafile)  #这个地方的data的类型是DataFramedata = data[u'肝气郁结证型系数']  #这里的data已经是DataFrame的一列,变成了Series了

上面这个第三行是啥意思呢?因为我们待会要用到的KMeans的输入数据类型是ndarray的行向量,所以先在这里把data的一列拿出来。

Step3,创建KMeans的分类器并对Step2中的数据进行聚类。

请看代码:

k = 4kmodel = KMeans(n_clusters = k, n_jobs = 2) #n_jobs是进程的数量,和cpu个数有关kmodel.fit(data.values.reshape((len(data),1)))c = pd.DataFrame(kmodel.cluster_centers_).sort_values(0) #对聚类中心排序w1 = c.rolling(2).mean().iloc[1:]w = [0] + list(w1[0]) + [data.max()]d_result = pd.cut(data, w, labels = range(k))

就这么简单,就7行就搞定了这个事。在这里,我有必要把这几行代码简要说一下。

第1-3行,就是拿Step2中的数据用KMeans算法给聚类,不是会得到4个分类么?每个分类不是会有一个中心点么?如果忘记了,请回过头去看看这篇文章:数据离散化及其KMeans算法实现的理解。

拿这4个圆心也是存放在第2行创建的这个KMeans的对象kmodel中,确切说在它的cluster_centers_中。它的值是下面图这样的,然后再对它们从小到大排序给到c。


Python聚类的方法_python聚类_03

KMeans聚类后的中心


第4行,然后我们再把它转成DataFrame类型,再排一下序(就是代码第4行干的事)

第5行,是做窗口平均的,也就是说以rolling的输入2为窗口大小求平均值。更直白一点,就是第c的(第1个值+第2个值)/2作为新的第2个值,第1个值就没了,c经过rolling(2)窗口平均后的结果是这样的。


Python聚类的方法_python聚类_04

窗口平均的结果


然后我们把上图中的第1个值NaN给切掉后再赋给w1。

第6行,是将0作为最小,将data中的最大值作为最大,加入到w1中,w就变成5个值了,cw1w分别如下图的左、中、右。


Python聚类的方法_python聚类_05

cw1w的结果


第7行,所有前面6行都是为这一行服务的,就是要把我们对data分类的5个分类的界限(值)确定下来之后,用cut函数将data分成5类。

Step4:把分类好后的结果给画出来。代码如下:

def cluster_plot(d, k):    plt.rcParams['font.sans-serif']=['SimHei'] #正常显示中文标签    plt.rcParams['axes.unicode_minus'] = False #正常显示负号        plt.figure(figsize=(8,3))    for j in range(0,k):        plt.plot(data[d==j],[j for i in d[d==j]],'o')            plt.ylim(-0.5, k-0.5)    return pltcluster_plot(d_result,k).show()

这里呢,定义了一个函数cluster_plot的函数,返回一个画好了cluster的pyplot。

绘制的结果见“03 效果分析”。

03 效果分析

下面这个图就是聚类完成的结果图。可以看出来,我们通过KMeans算法找到的几个分界点将900多个数据给很好的分成了4类。


Python聚类的方法_python 聚类_06

对原式数据cut后的结果


在没聚类之前的原始数据是这样的:


Python聚类的方法_python聚类_07

原始数据


上面那个图看着舒服多了。

在这篇文章中,我们用KMeans算法对数据进行聚类是非常简单、粗暴的。并没有指定距离的计算方法、初始的中心点、结束条件等,都是使用了sklearn.cluster中KMeans的默认值,如果需要更详细的了解需要去看看sklearn的官方文档。