一、相关知识点

对于无监督的K-Means聚类需要确定k值,最佳k值的确定有两种常用的评估方法,用于确定最佳k值:“簇内离差平方和拐点法”、“轮廓系数法”。

① 拐点法:在不同的k值下计算簇内的离差平方和,然后通过可视化的方法找到“拐点”所对应的k值

② 轮廓系数法:该方法综合考虑了簇的密集性与分散性两个信息,如果数据集被分割为理想的k个簇,那么对应的簇内样本会很密集,而簇间样本会很分散,轮廓系数的计算公式如下:

nba如何使用数据分析 nba数据分析方法_数据


其中,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')