NBA球员投篮数据可视化

news/2024/11/6 17:22:09/

640?wx_fmt=gif


最近看了公众号「Crossin的编程教室」的一篇文章。


是有关于NBA球员出手数据的可视化案例,原文链接如下。




个人感觉比较有趣,所以想着自己也来实现一波。


总体上来说差不多,可能就是美观点吧...



/ 01 / 篮球场


从网上找的篮球场尺寸图,如下。


640?wx_fmt=png


其中单位为英尺,NBA的球场尺寸为94英尺长,50英尺宽。


下图是我用CAD绘制半场尺寸图,本次绘图就是按照下面这个尺寸来的。


640?wx_fmt=png


有了尺寸,接下来就可以使用matplotlib进行绘制篮球场了。


主要是绘制矩形、圆形以及圆弧。


具体代码如下。


 

from matplotlib import pyplot as plt
from matplotlib.patches import Arc, Circle, Rectangle


def draw_ball_field(color='#20458C', lw=2):
    """
    绘制篮球场
    """

    # 新建一个大小为(6,6)的绘图窗口
    plt.figure(figsize=(66))
    # 获得当前的Axes对象ax,进行绘图
    ax = plt.gca()

    # 对篮球场进行底色填充
    lines_outer_rec = Rectangle(xy=(-250-47.5), width=500, height=470, linewidth=lw, color='#F0F0F0', fill=True)
    # 设置篮球场填充图层为最底层
    lines_outer_rec.set_zorder(0)
    # 将rec添加进ax
    ax.add_patch(lines_outer_rec)

    # 绘制篮筐,半径为7.5
    circle_ball = Circle(xy=(00), radius=7.5, linewidth=lw, color=color, fill=False)
    # 将circle添加进ax
    ax.add_patch(circle_ball)

    # 绘制篮板,尺寸为(60,1)
    plate = Rectangle(xy=(-30-7.5), width=60, height=-1, linewidth=lw, color=color, fill=False)
    # 将rec添加进ax
    ax.add_patch(plate)

    # 绘制2分区的外框线,尺寸为(160,190)
    outer_rec = Rectangle(xy=(-80-47.5), width=160, height=190, linewidth=lw, color=color, fill=False)
    # 将rec添加进ax
    ax.add_patch(outer_rec)

    # 绘制2分区的内框线,尺寸为(120,190)
    inner_rec = Rectangle(xy=(-60-47.5), width=120, height=190, linewidth=lw, color=color, fill=False)
    # 将rec添加进ax
    ax.add_patch(inner_rec)

    # 绘制罚球区域圆圈,半径为60
    circle_punish = Circle(xy=(0142.5), radius=60, linewidth=lw, color=color, fill=False)
    # 将circle添加进ax
    ax.add_patch(circle_punish)

    # 绘制三分线的左边线
    three_left_rec = Rectangle(xy=(-220-47.5), width=0, height=140, linewidth=lw, color=color, fill=False)
    # 将rec添加进ax
    ax.add_patch(three_left_rec)

    # 绘制三分线的右边线
    three_right_rec = Rectangle(xy=(220-47.5), width=0, height=140, linewidth=lw, color=color, fill=False)
    # 将rec添加进ax
    ax.add_patch(three_right_rec)

    # 绘制三分线的圆弧,圆心为(0,0),半径为238.66,起始角度为22.8,结束角度为157.2
    three_arc = Arc(xy=(00), width=477.32, height=477.32, theta1=22.8, theta2=157.2, linewidth=lw, color=color, fill=False)
    # 将arc添加进ax
    ax.add_patch(three_arc)

    # 绘制中场处的外半圆,半径为60
    center_outer_arc = Arc(xy=(0422.5), width=120, height=120, theta1=180, theta2=0, linewidth=lw, color=color, fill=False)
    # 将arc添加进ax
    ax.add_patch(center_outer_arc)

    # 绘制中场处的内半圆,半径为20
    center_inner_arc = Arc(xy=(0422.5), width=40, height=40, theta1=180, theta2=0, linewidth=lw, color=color, fill=False)
    # 将arc添加进ax
    ax.add_patch(center_inner_arc)

    # 绘制篮球场外框线,尺寸为(500,470)
    lines_outer_rec = Rectangle(xy=(-250-47.5), width=500, height=470, linewidth=lw, color=color, fill=False)
    # 将rec添加进ax
    ax.add_patch(lines_outer_rec)

    return ax


axs = draw_ball_field(color='#20458C', lw=2)

# 设置坐标轴范围
axs.set_xlim(-250250)
axs.set_ylim(422.5-47.5)
# 消除坐标轴刻度
axs.set_xticks([])
axs.set_yticks([])
# 添加备注信息
plt.annotate('By xiao F', xy=(100160), xytext=(178418))
plt.show()


最后得到下图。


640?wx_fmt=png

下面去获取球员的投篮数据。



/ 02 / 投篮数据


投篮数据来源于NBA官方网站——NBA Stats。


640?wx_fmt=png


在这个网页下打开开发者工具,找到下面这个请求。


640?wx_fmt=png


便能获取到球员的投篮数据,本次只获取球员的投篮点及是否得分的数据。


这里以「库里」为例,爬取代码如下。


 

import requests
import json

headers = {
        'User-Agent''Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
    }

# 球员职业生涯时间
years = [20182019]
for i in range(years[0], years[1]):
    # 赛季
    season = str(i) + '-' + str(i + 1)[-2:]
    # 球员ID
    player_id = '201939'
    # 请求网址
    url = 'https://stats.nba.com/stats/shotchartdetail?AheadBehind=&CFID=33&CFPARAMS=' + season + '&ClutchTime=&Conference=&ContextFilter=&ContextMeasure=FGA&DateFrom=&DateTo=&Division=&EndPeriod=10&EndRange=28800&GROUP_ID=&GameEventID=&GameID=&GameSegment=&GroupID=&GroupMode=&GroupQuantity=5&LastNGames=0&LeagueID=00&Location=&Month=0&OnOff=&OpponentTeamID=0&Outcome=&PORound=0&Period=0&PlayerID=' + player_id + '&PlayerID1=&PlayerID2=&PlayerID3=&PlayerID4=&PlayerID5=&PlayerPosition=&PointDiff=&Position=&RangeType=0&RookieYear=&Season=' + season + '&SeasonSegment=&SeasonType=Regular+Season&ShotClockRange=&StartPeriod=1&StartRange=0&StarterBench=&TeamID=0&VsConference=&VsDivision=&VsPlayerID1=&VsPlayerID2=&VsPlayerID3=&VsPlayerID4=&VsPlayerID5=&VsTeamID='
    # 请求结果
    response = requests.get(url=url, headers=headers)
    result = json.loads(response.text)

    # 获取数据
    for item in result['resultSets'][0]['rowSet']:
        # 是否进球得分
        flag = item[10]
        # 横坐标
        loc_x = str(item[17])
        # 纵坐标
        loc_y = str(item[18])
        with open('curry.csv''a+'as f:
            f.write(loc_x + ',' + loc_y + ',' + flag + '\n')


获取到的数据如下。


640?wx_fmt=png


其中可以通过设置球员ID以及赛季时间来获取不同的数据。


球员ID和赛季时间可以通过官网中的球员信息网页了解到。



/ 03 / 数据可视化


现在球场有了,投篮数据也有了,就可以来画图了。


使用matplotlib的散点图来实现。


 

import pandas as pd

# 读取数据
df = pd.read_csv('curry.csv', header=None, names=['width''height''type'])
# 分类数据
df1 = df[df['type'] == 'Made Shot']
df2 = df[df['type'] == 'Missed Shot']
# 绘制散点图
axs.scatter(x=df2['width'], y=df2['height'], s=30, marker='x', color='#A82B2B')
axs.scatter(x=df1['width'], y=df1['height'], s=30, marker='o', edgecolors='#3A7711', color="#F0F0F0", linewidths=2)


得到下图。


640?wx_fmt=png


来和官网的图对比一下。


640?wx_fmt=png


看起来还不错,匹配度还是蛮高的。


下面绘制投篮热力图,通过seaborn绘制,代码如下。


 

import seaborn as sns
import matplotlib as mpl

# 读取数据
df = pd.read_csv('curry.csv', header=None, names=['width''height''type'])


def colormap():
    """
    颜色转换
    """

    return mpl.colors.LinearSegmentedColormap.from_list('cmap', ['#C5C5C5''#9F9F9F''#706A7C''#675678''#713A71','#9D3E5E''#BC5245',  '#C86138''#C96239''#D37636''#D67F39''#DA8C3E''#E1A352'], 256)


# 绘制球员投篮热力图
shot_heatmap = sns.jointplot(df['width'], df['height'], stat_func=None, kind='kde', space=0, color='w', cmap=colormap())
# 设置图像大小
shot_heatmap.fig.set_size_inches(66)
# 图像反向
ax = shot_heatmap.ax_joint
# 绘制投篮散点图
ax.scatter(x=df['width'], y=df['height'], s=0.1, marker='o', color="w", alpha=1)
# 添加篮球场
draw_ball_field(color='w', lw=2)
# 将坐标轴颜色更改为白色
lines = plt.gca()
lines.spines['top'].set_color('none')
lines.spines['left'].set_color('none')
# 去除坐标轴标签
ax.axis('off')


得到结果如下。


640?wx_fmt=png


还是来看一下官网的图。


640?wx_fmt=png


两个效果都不错,不过边框我没调好,显得没那么好看。


库里投篮最密集的区域,篮下和三分线。

最后看一下于小F而言,印象比较深的球员,「科比」和「霍华德」。


「科比」的ID为977,职业生涯时间为1996年到2012年。


640?wx_fmt=png


全线开花,不少负角度投篮,甚至还有超远三分。


640?wx_fmt=gif


「霍华德」的ID为2730,职业生涯时间为2004年到2019年。


640?wx_fmt=png


魔兽霍华德,屈指可数的三分。


其他都是围绕着篮板的得分。


640?wx_fmt=gif


还有好多球员,就靠大伙自己去看啦!


推荐阅读


···END···

640?wx_fmt=jpeg

扫二维码关注



http://www.ppmy.cn/news/246414.html

相关文章

NBA表格_数据分析NBA历史前十球星排名

看了很多nba历史前十的排名,除了乔丹排第一之外,其他人的排名不断的有所变化,但历史前十大体上在乔丹、贾巴尔、张伯伦、詹姆斯、邓肯、拉塞尔、魔术师、科比、奥拉朱旺、奥尼尔、伯德这十一个人当中产生的情况被多数人所认可。为此&#xff…

NBA最伟大的50位球星

NBA最伟大的50位球星 洛鸣 于2006年2月7日17:10 [url]www.our-sky.com/oubb/310846.html[/url] -----------------------------------------------------------特别鸣谢-- 作者:上帝xiaoming-- 发布时间:2004-12-28 15:54:00 -------------------------…

冤大头?NBA球星库里花了 116 万买了一只猴头像,到底咋回事?

上面这个公号,是我的一个备用号,为了防止万一哪天大号失联,平时一周我也会发三篇左右的我的思考,读书笔记,认知感悟等文章,带领大家一起探索精神与财务自由之路。 大家好,我是校长。 最近 NFT 非…

AI 作画《NBA球星动漫头像》| 用stable diffusion生成

扩散模型原理 扩散模型是一种概率模型,通过逐步去噪一个正态分布变量来学习数据分布p(x),对应于学习长度为t的固定马尔可夫链的反向过程。模型可以通过训练去噪自编码器来实现(T 1…T),它们被训练来预测其输入的去噪变…

NBA篮球名人堂

NBA篮球名人堂 篮球名人堂,全称奈史密斯篮球名人纪念堂(Naismith Memorial Basketball Hall of Fame)。是一幢三层大楼,位于美国91号高速公路附近。占地54000平方英尺。1968年由马萨诸塞州斯普林菲尔德学院迁来。楼里陈列有篮球文…

NBA球星数据可视化分析-FineBI

目录 一、实验&#xff08;实训&#xff09;目的 二、实验&#xff08;实训&#xff09;原理或方法 三、仪器设备、材料 四、实验&#xff08;实训&#xff09;步骤 五、实训记录及结果 <---------------------------------木易白驹----------------------------------…

NBA球星生涯数据集分析

源码链接&#xff1a; https://download.csdn.net/download/qq_58012062/87541713?spm1001.2014.3001.5501 数据提取&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1kcttx000FfaLBk1QAJbBAw 提取码&#xff1a;jbbk 1 实验背景 NBA 作为世界上水平最高的篮球联赛…

NBA著名球星介绍

NBA著名球星介绍 迈克尔乔丹 毋庸置疑的篮球之神&#xff0c;六次总冠军&#xff0c;五次常规赛MVP&#xff0c;14次入选全明星他所取得的荣誉是其他任何NBA球员都无法比拟的&#xff0c;甚至从某种程度上说&#xff0c;乔丹代表这篮球这项运动&#xff0c;代表着在这项运动里所…