从零开始学Python【29】–K均值聚类(实战部分)

前言

我们接着《从零开始学Python【28】–K均值聚类(理论部分)》一文,继续跟大家分享一下如何借助于Python和R语言工具完成K均值聚类的实战。本次实战的数据来源于虎扑体育(https://nba.hupu.com/stats/players),我们借助于NBA球员的命中率和罚球命中率两个来给各位球员做一次“人以群分”的效果。

首先,我们使用pandas中的read_html函数读取虎扑体育网页中的球员数据表,然后再对数据作清洗(主要是数据类型的转换、变量的重命名和观测的删除):

# 加载第三包

importpandas aspd

importnumpy asnp

importmatplotlib.pyplot asplt

fromsklearn.cluster importKMeans

# 读取网页中的数据表

table = [] fori inrange( 1, 7): table.append(pd.read_html( ‘https://nba.hupu.com/stats/players/pts/%d’%i)[ 0])

# 所有数据纵向合并为数据框

players = pd.concat(table)

# 变量重命名

columns=[ ‘排名’, ‘球员’, ‘球队’, ‘得分’, ‘命中-出手’, ‘命中率’, ‘命中-三分’, ‘三分命中率’, ‘命中-罚球’, ‘罚球命中率’, ‘场次’, ‘上场时间’]players.columns=columns

# 数据类型转换

players.得分 = players.得分.astype( ‘float’)players.命中率 = players.命中率.str[:- 1].astype( ‘float’)/ 100

players.三分命中率 = players.三分命中率.str[:- 1].astype( ‘float’)/ 100

players.罚球命中率 = players.罚球命中率.str[:- 1].astype( ‘float’)/ 100

players.场次 = players.场次.astype( ‘int’)players.上场时间 = players.上场时间.astype( ‘float’)

# 删除行标签为0的记录

players.drop( 0,inplace= True)players.head()

本次一共获得286名球员的历史投篮记录,这些记录包括球员姓名、所属球队、得分、各命中率等信息,下面我们仅使用球员的命中率和罚球命中率来做聚类,主要是为了方便展现聚类效果的图形。首先,我们来看看这两个指标下的散点图:

# 中文和负号的正常显示

plt.rcParams[ ‘font.sans-serif’] = [ ‘Microsoft YaHei’]plt.rcParams[ ‘axes.unicode_minus’] = False

# 设置绘图风格

plt.style.use( ‘ggplot’)

# 绘制得分与命中率的散点图

players.plot(x= ‘罚球命中率’,y= ‘命中率’,kind= ‘scatter’)plt.show()

通过肉眼,似乎还无法对这286名球员进行聚类(画圈),如果画圈的话,该划为几类合适呢?一般我们可以通过迭代的方式选出合适的聚类个数,即让k值从1到K依次执行一遍,再查看每一次k值对应的簇内离差平方和之和的变化,如果变化幅度突然由大转小时,那个k值就是我们选择的合理个数。具体我们通过图形展现来说明上面的文字:

# 选择最佳的K值

X = players[[ ‘罚球命中率’, ‘命中率’]]K = range( 1,int(np.sqrt(players.shape[ 0])))

GSSE = []

fork inK: SSE = [] kmeans = KMeans(n_clusters=k, random_state= 10) kmeans.fit(X) labels = kmeans.labels_ centers = kmeans.cluster_centers_

forlabel inset(labels): SSE.append(np.sum(np.sum((players[[ ‘罚球命中率’, ‘命中率’]].loc[labels == label,]-centers[label,:])** 2))) GSSE.append(np.sum(SSE))

# 绘制K的个数与GSSE的关系

plt.plot(K, GSSE, ‘b*-‘)plt.xlabel( ‘聚类个数’)plt.ylabel( ‘簇内离差平方和’)plt.title( ‘选择最优的聚类个数’)plt.show()

从图中结果显示,当k为7时,看上去簇内离差平方和之和的变化已慢慢变小,那么,我们不妨就将球员聚为7类。如下为聚类效果的代码:

#调用sklearn的库函数

num_clusters = 6

kmeans = KMeans(n_clusters=num_clusters, random_state= 1)kmeans.fit(X)

# 聚类结果标签

players[ ‘cluster’] = kmeans.labels_

# 聚类中心

centers = kmeans.cluster_centers_

# 绘制散点图

plt.scatter(x = X.iloc[:, 0], y = X.iloc[:, 1], c = players[ ‘cluster’], s= 50, cmap= ‘rainbow’)plt.scatter(centers[:, 0], centers[:, 1], c= ‘k’, marker = ‘*’, s = 180)plt.xlabel( ‘罚球命中率’)plt.ylabel( ‘命中率’)

# 图形显示

plt.show()

上图中,散点的不同颜色表示的是聚为不同的簇,黑色五角星为各簇的中心点,看上去其聚类效果有那么点意思。到此,关于使用Python实现K均值聚类的实战我们就分享到这里,接下来将使用R语言重新复现一遍,希望对R语言熟悉的朋友有一点的帮助。如下是R语言的复现脚本:

# 加载第三方包

library(ggplot2)

# 读取Python中现成下好的数据

players = read.csv(file = file.choose())head(players)

# 绘制罚球命中率和命中率散点图

ggplot(data = players, mapping = aes(x = 罚球命中率, y = 命中率)) + geom_point()

# 自定义函数选择最佳的K值

tot.wssplot <- function(data, nc, seed= 1234){

#假设分为一组时的总的离差平方和 tot.wss <- (nrow(data)- 1)*sum(apply(data, 2,var)) for(i in2:nc){

#必须指定随机种子数set.seed(seed) tot.wss[i] <- sum(kmeans(data, centers=i)$withinss) } ggplot(data = NULL, mapping = aes(x = 1:nc, y = tot.wss)) + geom_point() + geom_line(color = ‘steelblue’, size = 1) + labs(x = ‘聚类个数’, y = ‘簇内离差平方和’, title = ‘选择最优的聚类个数’) + theme(plot.title = element_text(hjust = 0.5, face = ‘bold’)) }

#绘制各种组数下的总的组内平方和图

tot.wssplot(data = players[,c( ‘罚球命中率’, ‘命中率’)], nc = as.integer(sqrt(nrow(players))))

# 聚类

clust <- kmeans(x = players[,c( ‘罚球命中率’, ‘命中率’)], centers = 7)centers = clust$centersplayers$cluster = clust$cluster

# 聚类效果图

ggplot() + geom_point(data = players, mapping = aes(x = 罚球命中率, y = 命中率, color = factor(cluster)),size = 1.5) + geom_point(aes(x = centers[, 1], y = centers[, 2]), fill = ‘black’, shape = 18, size = 3) + labs(title = ‘聚类效果图’) + theme(plot.title = element_text(hjust= 0.5, face = ‘bold’),legend.position= “none”)

结语

OK,关于使用Python和R语言完成K均值聚类的实战我们就分享到这里,如果你有任何问题,欢迎在公众号的留言区域表达你的疑问。同时,也欢迎各位朋友继续转发与分享文中的内容,让更多的人学习和进步。

 

END.

系列文章:

从零开始学Python【20】–线性回归(理论部分)

从零开始学Python【21】–线性回归(实战部分)

从零开始学Python【22】–线性回归诊断(第一部分)

从零开始学Python【23】–线性回归诊断(第二部分)

从零开始学Python【24】–岭回归及LASSO回归(理论部分)

从零开始学Python【25】–岭回归及LASSO回归(实战部分)

从零开始学Python【26】–Logistic回归(理论部分)

从零开始学Python【27】–Logistic回归(实战部分)

从零开始学Python【28】–K均值聚类(理论部分)

You may also like...

发表评论

切换注册

登录

忘记密码 ?

切换登录

注册