1. 程式人生 > >利用Python實現K-Means聚類並進行圖形化展示

利用Python實現K-Means聚類並進行圖形化展示

利用K-means進行聚類,顯示聚類結果的各類別的數量,最終進行圖形化展示 。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import cx_Oracle
from sklearn.preprocessing import MinMaxScaler,StandardScaler
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.cluster import KMeans #匯入K均值聚類演算法
import os
file = open('test.xlsx','rb')
data = pd.read_excel(file)
file.close()
data.set_index('CONS_NO',inplace=True)
#刪除指標
data.drop('label_訴求行為',axis=1,inplace=True)
#填充nan值為0
data.fillna(0, inplace = True)
#標準化
for i in data.columns:
    if i=='TS_FLAG':
        data = pd.get_dummies(data,columns=[i])  #離散值進行One-Hot編碼
    else:    
        data[i]=\
            StandardScaler().fit_transform(data[i].values.reshape(-1,1)).reshape(1,-1)[0]  #數值標準化

plt.rcParams['font.sans-serif'] = ['SimHei'] #用來正常顯示中文標籤

distance=pd.DataFrame(index=range(1,15),columns=['類內距離','類間距離']) 
for k in range(3,11):
    kmodel=KMeans(n_clusters=k)
    kmodel.fit(data)
    r1 = pd.Series(kmodel.labels_).value_counts()  #統計各個類別的數目
      #重命名錶頭
    print(r1)
    distance_in=0
    distance_ot=0
    for i in range(k):
        group=kmodel.labels_==i
        members=data[group]
        for v in np.mat(members):
            distance_in += np.linalg.norm(v - kmodel.cluster_centers_[i])  #預設為二範數,即歐式距離
        for j in range(k):
            if i<j:
                distance_ot +=np.linalg.norm(kmodel.cluster_centers_[i]-kmodel.cluster_centers_[j])
    distance.loc[k,'類內距離']=distance_in
    distance.loc[k,'類間距離']=distance_ot
    print('完成聚類數為 {} 聚類!'.format(k))
#聚類6類

k = 6
kmodel = KMeans(n_clusters = k, n_jobs = 1) #n_jobs是並行數,一般等於CPU數較好
kmodel.fit(data) #訓練模型
r1 = pd.Series(kmodel.labels_).value_counts()  #統計各個類別的數目
r2 = pd.DataFrame(kmodel.cluster_centers_)     #找出聚類中心
r = pd.concat([r2, r1], axis = 1)              #橫向連線(0是縱向),得到聚類中心對應的類別下的數目
r.columns = list(data.columns) + [u'類別數目']  #重命名錶頭
colr = ['#E15759', '#4E79A7', '#76B7B2', '#F28E2B','blue','#F45E2B','#F67E2B']
plt.figure(figsize = (10, 8))
for i in r.index:
    if r['類別數目'][i] > 10:
        plt.plot(r.columns[:-1], r.loc[i, r.columns[:-1]], color = colr[i], label = i, linewidth=2)
plt.legend(loc = 0, fontsize=14)
plt.axis('tight')
plt.xticks(fontsize=12,rotation=30)  
plt.yticks(fontsize=12)
plt.xlabel('標籤名' ,fontsize=20)
plt.ylabel('中心點' ,fontsize=20)
plt.rcParams['xtick.labelsize'] = 20
plt.rcParams['ytick.labelsize'] = 20
plt.show()

data['label_總聚類'] = kmodel.labels_   #得到聚類結果