一、相关知识点
对于无监督的K-Means聚类需要确定k值,最佳k值的确定有两种常用的评估方法,用于确定最佳k值:“簇内离差平方和拐点法”、“轮廓系数法”。
① 拐点法:在不同的k值下计算簇内的离差平方和,然后通过可视化的方法找到“拐点”所对应的k值
② 轮廓系数法:该方法综合考虑了簇的密集性与分散性两个信息,如果数据集被分割为理想的k个簇,那么对应的簇内样本会很密集,而簇间样本会很分散,轮廓系数的计算公式如下:
其中,a(i)体现了簇内的密集性,代表样本i与同簇内其他样本点距离的平均值;b(i)反映了簇间的分散性,其计算过程是:样本i与其他非同簇样本点距离的平均值,然后从平均值中挑选出最小值。
二、代码
import pandas as pd
import numpy as n
# 读取网页中的数据表
table = []
for i in range(1,7):
table.append(pd.read_html('https://nba.hupu.com/stats/players/pts/%d' %i)[0])#使用pandas中的read_html函数读取虎扑体育网页中的球员数据表
# 所有数据纵向合并为数据框
players = pd.concat(table)
# 变量重命名
columns=['排名','球员','球队','得分','命中-出手','命中率','命中-三分','三分命中率','命中-罚球','罚球命中率','场次','上场时间']
players.columns=columns
players.drop(0,inplace=True)
print(players)
players.to_csv(r"../data/players.csv",encoding='utf_8_sig')#将结果写入本地文件players.csv
#原始数据中命中率的格式为x%,需要进行标准化处理转化为数值形式,小数点后保留3位小数。
# 读取球员数据
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
players = pd.read_csv(r'../data/players.csv')
players.head()
# 中文和负号的正常示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
#绘制得分与命中率的散点图
import seaborn as sns
sns.lmplot(x = '得分',y = '命中率',data = players,
fit_reg = False, scatter_kws = {'alpha':0.8,'color':'steelblue'})
plt.show()
# 构造自定义函数,用于绘制不同k值和对应总的簇内离差平方和的折线图
def k_SSE(X, clusters):
# 选择连续的K种不同的值
K = range(1,clusters+1)
# 构建空列表用于存储总的簇内离差平方和
TSSE = []
for k in K:
# 用于存储各个簇内离差平方和
SSE = []
from sklearn.cluster import KMeans
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')