# 導入第三方包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import metrics
# 隨機生成三組二元正態分布隨機數
np.random.seed(1234)
mean1 = [0.5, 0.5]
cov1 = [[0.3, 0], [0, 0.3]]
x1, y1 = np.random.multivariate_normal(mean1, cov1, 1000).T
print(x1.shape)
print(y1.shape)
mean2 = [0, 8]
cov2 = [[1.5, 0], [0, 1]]
x2, y2 = np.random.multivariate_normal(mean2, cov2, 1000).T
mean3 = [8, 4]
cov3 = [[1.5, 0], [0, 1]]
x3, y3 = np.random.multivariate_normal(mean3, cov3, 1000).T
# 繪制三組數據的散點圖
plt.scatter(x1,y1)
plt.scatter(x2,y2)
plt.scatter(x3,y3)
# 顯示圖形
plt.show()

# 構造自定義函數,用於繪制不同k值和對應總的簇內離差平方和的折線圖
def k_SSE(X, clusters):
# 選擇連續的K種不同的值
K = range(1,clusters+1)
# 構建空列表用於存儲總的簇內離差平方和
TSSE = []
for k in K:
# 用於存儲各個簇內離差平方和
SSE = []
kmeans = KMeans(n_clusters=k)
kmeans.fit(X)
# 返回簇標簽
labels = kmeans.labels_
# 返回簇中心
centers = kmeans.cluster_centers_
# 計算各簇樣本的離差平方和,並保存到列表中
for label in set(labels):
SSE.append(np.sum((X.loc[labels == label,]-centers[label,:])**2))
# 計算總的簇內離差平方和
TSSE.append(np.sum(SSE))
# 中文和負號的正常顯示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 設置繪圖風格
plt.style.use('ggplot')
# 繪制K的個數與GSSE的關系
plt.plot(K, TSSE, 'b*-')
plt.xlabel('簇的個數')
plt.ylabel('簇內離差平方和之和')
# 顯示圖形
plt.show()
# 將三組數據集匯總到數據框中
X = pd.DataFrame(np.concatenate([np.array([x1,y1]),np.array([x2,y2]),np.array([x3,y3])], axis = 1).T)
print(X.shape)
print(X.head())
# 自定義函數的調用
k_SSE(X, 15)

# 構造自定義函數,用於繪制不同k值和對應輪廓系數的折線圖
def k_silhouette(X, clusters):
K = range(2,clusters+1)
# 構建空列表,用於存儲個中簇數下的輪廓系數
S = []
for k in K:
kmeans = KMeans(n_clusters=k)
kmeans.fit(X)
labels = kmeans.labels_
# 調用字模塊metrics中的silhouette_score函數,計算輪廓系數
S.append(metrics.silhouette_score(X, labels, metric='euclidean'))
# 中文和負號的正常顯示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 設置繪圖風格
plt.style.use('ggplot')
# 繪制K的個數與輪廓系數的關系
plt.plot(K, S, 'b*-')
plt.xlabel('簇的個數')
plt.ylabel('輪廓系數')
# 顯示圖形
plt.show()
# 自定義函數的調用
k_silhouette(X, 15)

# 自定義函數,計算簇內任意兩樣本之間的歐氏距離
def short_pair_wise_D(each_cluster):
mu = each_cluster.mean(axis = 0)
Dk = sum(sum((each_cluster - mu)**2)) * 2.0 * each_cluster.shape[0]
return Dk
# 計算簇內的Wk值
def compute_Wk(data, classfication_result):
Wk = 0
label_set = set(classfication_result)
for label in label_set:
each_cluster = data[classfication_result == label, :]
Wk = Wk + short_pair_wise_D(each_cluster)/(2.0*each_cluster.shape[0])
return Wk
# 計算GAP統計量
def gap_statistic(X, B=10, K=range(1,11), N_init = 10):
# 將輸入數據集轉換為數組
X = np.array(X)
# 生成B組參照數據
shape = X.shape
tops = X.max(axis=0)
bots = X.min(axis=0)
dists = np.matrix(np.diag(tops-bots))
rands = np.random.random_sample(size=(B,shape[0],shape[1]))
for i in range(B):
rands[i,:,:] = rands[i,:,:]*dists+bots
# 自定義0元素的數組,用於存儲gaps、Wks和Wkbs
gaps = np.zeros(len(K))
Wks = np.zeros(len(K))
Wkbs = np.zeros((len(K),B))
# 循環不同的k值,
for idxk, k in enumerate(K):
k_means = KMeans(n_clusters=k)
k_means.fit(X)
classfication_result = k_means.labels_
# 將所有簇內的Wk存儲起來
Wks[idxk] = compute_Wk(X,classfication_result)
# 通過循環,計算每一個參照數據集下的各簇Wk值
for i in range(B):
Xb = rands[i,:,:]
k_means.fit(Xb)
classfication_result_b = k_means.labels_
Wkbs[idxk,i] = compute_Wk(Xb,classfication_result_b)
# 計算gaps、sd_ks、sk和gapDiff
gaps = (np.log(Wkbs)).mean(axis = 1) - np.log(Wks)
sd_ks = np.std(np.log(Wkbs), axis=1)
sk = sd_ks*np.sqrt(1+1.0/B)
# 用於判別最佳k的標准,當gapDiff首次為正時,對應的k即為目標值
gapDiff = gaps[:-1] - gaps[1:] + sk[1:]
# 中文和負號的正常顯示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 設置繪圖風格
plt.style.use('ggplot')
# 繪制gapDiff的條形圖
plt.bar(np.arange(len(gapDiff))+1, gapDiff, color = 'steelblue')
plt.xlabel('簇的個數')
plt.ylabel('k的選擇標准')
plt.show()
# 自定義函數的調用
gap_statistic(X)

# 讀取iris數據集
iris = pd.read_csv(r'F:\\python_Data_analysis_and_mining\\15\\iris.csv')
# 查看數據集的前幾行
print(iris.head())
# 提取出用於建模的數據集X
X = iris.drop(labels = 'Species', axis = 1)
# 構建Kmeans模型
kmeans = KMeans(n_clusters = 3)
kmeans.fit(X)
# 聚類結果標簽
X['cluster'] = kmeans.labels_
# 各類頻數統計
a = X.cluster.value_counts()
print(a)
# 導入第三方模塊
import seaborn as sns
# 三個簇的簇中心
centers = kmeans.cluster_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()

# 增加一個輔助列,將不同的花種映射到0,1,2三種值,目的方便后面圖形的對比
iris['Species_map'] = iris.Species.map({'virginica':0,'setosa':1,'versicolor':2})
# 繪制原始數據三個類別的散點圖
sns.lmplot(x = 'Petal_Length', y = 'Petal_Width', hue = 'Species_map', data = iris, markers = ['^','s','o'],
fit_reg = False, scatter_kws = {'alpha':0.8}, legend_out = False)
plt.xlabel('花瓣長度')
plt.ylabel('花瓣寬度')
# 圖形顯示
plt.show()

# 導入第三方模塊
import pygal
# 調用Radar這個類,並設置雷達圖的填充,及數據范圍
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('E:\\radar_chart.svg')
# 讀取球員數據
players = pd.read_csv(r'F:\\python_Data_analysis_and_mining\\15\\players.csv')
print(players.shape)
print(players.head())
# 繪制得分與命中率的散點圖
sns.lmplot(x = '得分', y = '命中率', data = players,
fit_reg = False, scatter_kws = {'alpha':0.8, 'color': 'steelblue'})
plt.show()


from sklearn import preprocessing
# 數據標准化處理
X = preprocessing.minmax_scale(players[['得分','罰球命中率','命中率','三分命中率']])
# 將數組轉換為數據框
X = pd.DataFrame(X, columns=['得分','罰球命中率','命中率','三分命中率'])
# 使用拐點法選擇最佳的K值
k_SSE(X, 15)

# 使用輪廓系數選擇最佳的K值
k_silhouette(X, 15)

# 使用間隙統計量選擇最佳的K值
gap_statistic(X, B = 20, K=range(1, 16))

# 將球員數據集聚為3類
kmeans = KMeans(n_clusters = 3)
kmeans.fit(X)
# 將聚類結果標簽插入到數據集players中
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('E:\\radar_chart01.svg')
