1、思路
應用Kmeans聚類時,需要首先確定k值,如果k是未知的,需要先確定簇的數量。其方法可以使用拐點法、輪廓系數法(k>=2)、間隔統計量法。若k是已知的,可以直接調用sklearn子模塊cluster中Kmeans方法,對數據進行切割。
另外如若數據集不規則,存在量綱上的差異,也需要對其進行標准化處理。
2、數據的標准化處理

(minmax_scale為sklearn子模塊processing 中 的函數),第一種方法為壓縮變量為mean=0,std=1的無量綱數據,第二種方式會壓縮變量為[0,1]之間無量綱數據 。
3、案例
1)對iris聚類(已知簇類的情況)
情況1,已知k值,k=3
調用KMeans模塊
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']
iris = pd.read_csv(r'iris.csv')
# 設置聚為3類,n_clusters =3
X = iris.drop(labels = 'Species',axis = 1)
kmeans = KMeans(n_clusters =3 )
kmeans.fit(X)
X['cluster'] = kmeans.labels_
X.cluster.value_counts()
# 繪制花瓣長度與寬度的散點圖
import seaborn as sns
centers = kmeans.cluster_centers_
print(centers)
sns.lmplot(x = 'Petal_Length',
y= 'Petal_Width',
hue = 'cluster',
markers = ['^','s','o'],
data = X,
fit_reg= False,
scatter_kws = {'alpha':0.8},
legend_out = False
)
plt.scatter(centers[:,2], centers[:,3], marker = '*',color = 'black', s =130) # 繪制簇中心點
plt.xlabel('花瓣長度')
plt.ylabel('花瓣寬度')
plt.show()
iris['Species_map'] = iris.Species.map({'virginica':0,'setosa':1,"versicolor":2}) # 3種類型進行映射到0,1,2
sns.lmplot(x = 'Petal_Length',
y= 'Petal_Width',
hue = 'Species_map',
markers = ['^','s','o'],
data = iris,
fit_reg= False,
scatter_kws = {'alpha':0.8},
legend_out = False )
plt.xlabel('花瓣長度')
plt.ylabel('花瓣寬度')
plt.show()
生成圖形如下:

對簇中心做雷達圖
import pygal
radar_chart = pygal.Radar(fill = True)
radar_chart.x_labels = ['花萼長度','花萼寬度', '花瓣長度','花瓣寬度']
# 雷達圖區域繪制
radar_chart.add('C1',centers[0])
radar_chart.add('C2',centers[1])
radar_chart.add('C3',centers[2])
radar_chart.render_to_file('radar_chart.svg')
生成如下圖形,C1類型的花,花萼長和花瓣長都是最大的。C2類型的花,對應的3個指標值都比較小,C3類型的花,3個指標的平均值,恰好落在C1和C2之間。

2)NBA球員數據集聚類(未知k值)
數據集

選定得分、命中率,三分命中率,罰球命中率四個維度進行分析,觀察數據情況,需進行標准化。
- 先對得分和命中率作散點圖,進行觀察
sns.lmplot(x = '得分',
y = '命中率',
data = players,
fit_reg = False,
scatter_kws = {'alpha': 0.8,'color': 'steelblue'}
)
plt.show()

肉眼無法進行觀察數據集適合分為幾個簇。分別采用 以上確定k值的3種方法進行測試。
拐點法:
from sklearn import preprocessing X = preprocessing.minmax_scale(players[['得分','罰球命中率','命中率','三分命中率']]) # 數據集的標准化 X = pd.DataFrame(X, columns=['得分','罰球命中率','命中率','三分命中率']) k_SSE(X,15)

結果看出,k值在3、4斜率變化比較明顯,在5以后斜率保持一定的水平。所以k取3,4,5均有可能。在比較其他方法。
輪廓系數法及Gap statistic法可視化效果如下:


結合上圖,輪廓系數在大於0的情況下,最大值對應的k值為2,統計量法首次出現正值的k值為3,綜合考慮以上三種方法取k值為3,即將數據集分為3個簇最理想。
- 對得分和命中率進行聚類
kmeans = KMeans(n_clusters = 3)
kmeans.fit(X)
players['cluster'] = kmeans.labels_
centers = []
for i in players.cluster.unique():
centers.append(players.ix[players.cluster == i, ['得分','罰球命中率','命中率','三分命中率']].mean())
centers = np.array(centers)
sns.lmplot(x = '得分',
y = '命中率',
hue = 'cluster',
data = players,
markers = ['^','s','o'],
fit_reg = False,
scatter_kws = {'alpha': 0.8},
legend = False
)
plt.scatter(centers[:,0],centers[:,2],c = 'k',marker = '*',s =180)
plt.xlabel('得分')
plt.ylabel('命中率')
plt.show()
# 雷達圖繪制
centers_std = kmeans.cluster_centers_
radar_chart = pygal.Radar(fill = True) # 設置填充型雷達圖
radar_chart.x_labels = ['得分','罰球命中率','命中率','三分命中率']
radar_chart.add('C1', centers_std[0])
radar_chart.add('C2', centers_std[1])
radar_chart.add('C3', centers_std[2])
radar_chart.render_to_file('radar_charts.svg')
結果如下圖:


由聚類結果可以發現,三角形區域代表的球員屬於低得分低命中率類型,命中率普遍低於50%,方形區域代表低得分高命中率的球員,圓形區域球員與三角形區域球員具有類似的命中率,單圓形區域球員具有高得分。且該區域存在部分球員具有高得分且高命中率。通過對比雷達圖,C1、C2類球員平均得分差不多,但C2具有更高的命中率。平均罰球命中率和三分球命中率上來看,C1球員也要明顯高於C2.
