一.选题的背景

随着国家对体育教育的重视,篮球运动也越来越被大家所关注。本次分析围绕CBA福建队在全国各地的比赛信息分析,利用数据可视化的技术,将近期CBA福建队比赛情况对比展示出来。数据分析目标将数据图像化、简洁化,使得比赛情况可以正确地客观反映;有利于人们快速地了解CBA比赛情况,了解我们福建队的主客场胜率,比赛比分情况等数据,使更多人了解篮球精神并热爱篮球运动。

二.大数据分析设计方案

本数据集的数据内容包含着主客队的球队名单,比赛的时间点,主客队的比分情况。及采用了分布分析和对比分析,统计分析,正态性分析等数据特征分析来诠释CBA福建队的比赛数据。本次方案会先用爬虫技术,获取最近CBA福建队的比赛数据,然后通过把这些数据可视化,简洁明了的让大家看到,了解最近CBA福建队的比赛状态。

三.数据分析步骤

(1)数据源:本次数据是在CBA数据中心的网页采集得到的,网址为http://cbadata.sports.sohu.com/teams/team_players/Te013,进入网页,按F12打开开发者模式,分析网页源代码。这里主要获取了球队名、比赛时间、得分情况、比分情况等信息。具体是通过页面的结构分析,可以得到各个数据之间的便签都有关联的关系。然后运用python中的requests、pandas、BeautifulSoup等库获取大概三百条左右的比赛信息数据,爬下的数据存于一个CBA福建队.xlsx文件。主要爬取的内容是CBA福建队数据中心的每场比赛信息的球队、主队名及得分、客队名及得分、主队和客队的比分情况。

(2)数据清洗:用爬虫爬下数据后,发现并没有重复值,缺失值,异常值的问题出现。所以仅用了 plt.rcParams['font.sans-serif']=['SimHei'](为图表的中文文本设置默认字体,以避免中文显示乱码问题);plt.rcParams['axes.unicode_minus'] = False(解决坐标值为复数时无法显示负号的问题)进行数据清理。

(3)大数据分析过程及采用的算法:本次分析系用到数据分析算法:1.快速排序法。算法步骤: 从数列中挑出一个元素,称为 “基准”(pivot),重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。2.推排序算法。算法步骤:创建一个堆H[0..n-1]把堆首(最大值)和堆尾互换把堆的尺寸缩小 1,并调用 shift_down(0), 目的是把新的数组顶端数据调整到相应位置重复步骤2,直到堆的尺寸为1。

(4)数据可视化

1.首先通过一个环形图展示了CBA福建队xlsx.中的CBA福建队比赛中主队和客队队伍比分情况,根据CBA比赛两队比分情况环状图的环状分布大小比例看出每一环并不是分布的很均匀但也不是相差很大,可以看出篮球比赛得分并不是很稳定,但是幅度不会太大。

2.以多组柱形图的形式展示了CBA福建队比赛数据.xlsx中的CBA福建队比赛中主队和客队队伍得分情况。可以清楚的看到福建主客场队的得分情况。从图中可得知,在主场中,福建队的得分效率更高。

3.以折线图的形式展示了CBA福建队比赛数据.xlsx中的CBA福建队比赛中主队和客队队伍得分情况。通过该折线图可知,主队得分最低的一次是在2022年10月22日,最高的一次在2022年10月30日;客队得分最低的一次是在2022年10月30日,最高的一次在2022年10月13日。成绩都是波浪起伏,没有很是稳定发挥。还需继续努力。

4.以箱型图的形式展示了CBA福建队比赛数据.xlsx中的CBA福建队比赛中主队和客队队伍得分情况。通过该箱型图可知,2022年10月份比赛数据主队的箱型图较与客队来说较短,说明主队的得分多集中分布在比较小的范围内,而客队的得分分布比较离散,得分间的差异比较大。在2022年10月份的比赛中主队得分存在异常值,客队得分则不存在异常值。

5.以对比条形图的形式展示了CBA福建队比赛数据.xlsx中的CBA福建队比赛中主队和客队队伍得分情况。在该图中有两个子图,其中左边的图表展示了主队得分情况,右侧的图表展示了客队得分情况。由该图可知主队是在2022年10月22日得分最低,在2022年10月30日得分最高;客队是在2022年10月30日得分最低,在2022年10月13日得分最高。

6.以对比饼图的形式展示了CBA福建队比赛数据.xlsx中的CBA福建队比赛中主队和客队队伍得分情况。从中可以看出主队得分情况分布的更均衡,而客队得分情况相差稍微较大。所以可得出得分受主客队的影响。

7.以杠铃图的形式展示了CBA福建队比赛数据.xlsx中的CBA福建队比赛中主队和客队队伍得分情况。从该图可以看出2022年10月30日的那场CBA比赛中主队和客队的得分相差最多,在2022年10月11日的比赛中两队的得分相差最少。

(5)完整源代码(以及输出结果)

1.数据爬虫

import pandas as pdimport xlwtimport openpyxlimport requestsfrom bs4 import BeautifulSoupurl = 'http://cbadata.sports.sohu.com/teams/team_players/Te013'headers = { "Cookie": "IPLOC=CN5000; SUV=211206094136CEYA; gidinf=x099980109ee145e3691f94740000bca0d8b9fa5c47c; t=1638770110650", "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36 Edg/96.0.1054.43'}def getDetailInfo(url): print(url) res = requests.get(url, headers=headers).content.decode('utf-8') #对每一个网页发请求 soup = BeautifulSoup(res, "html.parser") allInfo = soup.select(".area > .cutE > div > table > tr")[1:] #排除掉第一个空值 (表头) singleInfo = [] #存每一个球队的所有比赛信息 for i in allInfo: title = soup.select("title")[0].string.split(':')[-1] #CBA球队介绍: 分割取冒号之后的部分 time = i.contents[1].string # 时间 zhudui = i.contents[3].string # 主队 score = i.contents[5].string # 比分情况 score = score.replace(' ','') score = score.replace('\n','') score = score.replace('\t','') scoreList = score.split(':') # print(score.split(':')) ke = i.contents[7].string # 客队 singleInfo.append([title,time,zhudui,scoreList[0],ke,scoreList[1],score]) return singleInfores = requests.get(url, headers=headers).content.decode('utf-8')soup = BeautifulSoup(res, "html.parser")allList = soup.select(".area > .cutG > h2 > span > select > option") #拿到所有球队的链接allInfo = []for i in allList: if i['value'] != '0' and i['value']: singleUrl = 'http://cbadata.sports.sohu.com/teams/team_players/Te013' + str(i['value']) #拼接真实url singleInfo = getDetailInfo(singleUrl) #传入函数 allInfo.extend(singleInfo)df = pd.DataFrame(allInfo) #转为dataframedf.columns = ['球队名', '比赛时间', '主队', '得分', '客队','得分','比分情况'] #设置表头df.to_excel('CBA福建队.xlsx', encoding='utf_8_sig') #存入excel

2. 可视化图表代码

(1)CBA比赛两队比分情况环形图

import pandas as pdimport matplotlib.pyplot as pltimport xlwings as xw# 为图表的中文文本设置默认字体,以避免中文显示乱码问题plt.rcParams['font.sans-serif']=['SimHei']# 解决坐标值为复数时无法显示负号的问题plt.rcParams['axes.unicode_minus'] = False#导入数据df = pd.read_excel("CBA福建队.xlsx")#取前十项代码df=df.head(10)#生成一个图框figure = plt.figure()#从excel表格中定义x和y轴的数据x = df['比分情况']y = df['得分']#绘制饼图plt.pie(y, labels = x, autopct = '%.2f%%', pctdistance = 0.85, radius = 1.0, labeldistance = 1.1, wedgeprops = {'width' : 0.3, 'linewidth' : 2, 'edgecolor' : 'white'})#设置图像标题plt.title(label = 'CBA比赛两队比分详情', fontdict = {'color' : 'black', 'size' : 30}, loc = 'center')#显示图例plt.legend(ncol=2,loc="lower right")plt.show(block=True)

(2)CBA福建队比赛两队得分详情多组柱形图

import pandas as pdimport matplotlib.pyplot as pltimport timeimport numpy as np# 处理中文乱码问题plt.rcParams["font.sans-serif"] = ["SimHei"]plt.rcParams["axes.unicode_minus"] = False#导入数据df = pd.read_excel("福建队比赛数据.xlsx")print(str(df["比赛时间"][0])[0:9])# 读取表格,将所有数据放入data中date = []#取比赛时间的前十个字符for i in range(9): date.append(str(df["比赛时间"][i])[0:9])print(date)df["比赛时间"].head()x = np.arange(9)#柱形的宽度bar_width = 0.2#根据多组数据绘制柱形图plt.bar(x, df["主队得分"], color='b', width=bar_width, tick_label=date)plt.bar(x + bar_width, df["客队得分"], color='r', width=bar_width)# 设置x轴,y轴坐标标题plt.xlabel("比赛时间", fontdict={'size': 15})plt.ylabel('得分', fontdict={'size': 15})#设置图像标题plt.title("福建队得分详情", fontdict={'size': 20})# 设置图例title = ["主队得分", "客队得分"]plt.tight_layout()plt.legend(title, loc='upper right')# 将x轴标签旋转plt.tick_params(axis='x', labelrotation=20)plt.show()

(3)CBA福建队比赛两队得分详情折线图

import pandas as pdimport matplotlib.pyplot as pltimport numpy as np# 处理中文乱码问题plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False#导入数据df = pd.read_excel("福建队比赛数据.xlsx")#从excel表格中定义x和y轴的数据y_zd = df['主队得分']y_kd = df['客队得分']data_x = df['比赛时间']#生成一个画框fig = plt.figure()#将画布分割为1行1列,图像画在从左往右从上到下的第一块ax = fig.add_subplot(111)#绘制折线图ax.plot(data_x,y_zd,color='b',linewidth=2,label='主队得分情况')ax.plot(data_x,y_kd,color='r',linestyle='--',linewidth=2,label='客队得分情况')#设置图像标题ax.set_title('福建队得分详情',fontdict={'size': 20})# 设置x轴,y轴坐标标题ax.set_xlabel('比赛时间',fontdict={'size': 15})ax.set_ylabel('得分',fontdict={'size': 15})# 将x轴标签旋转plt.tick_params(axis='x', labelrotation=20)#显示图例ax.legend(loc="upper right")plt.show()

(4)CBA福建队比赛两队得分详情箱型图

import pandas as pdimport matplotlib.pyplot as pltimport numpy as np# 处理中文乱码问题plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False#导入数据df = pd.read_excel("福建队比赛数据.xlsx")#从excel表格中定义x和y轴的数据data_zd=df['主队得分']data_kd=df['客队得分']#绘制箱型图plt.boxplot([data_zd,data_kd],labels=('主队得分','客队得分'),widths=0.5,vert=False,patch_artist = True,boxprops = {'color':'r','facecolor':'b'})#设置图像标题plt.title(label = '福建队得分详情', fontdict = {'color' : 'black', 'size' : 20}, loc = 'center')plt.show()

(5)CBA福建队比赛主队得分和客队得分对比条形图

import pandas as pdimport matplotlib.pyplot as pltimport numpy as np# 处理中文乱码问题plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# 添加无指向型注释文本def autolabel(ax, rects): """ 在每个矩形条的上方附加一个文本标签, 以显示其高度""" for rect in rects: width = rect.get_width() # 获取每个矩形条的高度 ax.text(width + 3, rect.get_y(), s='{}'.format(width), ha='center', va='bottom')# 导入数据df = pd.read_excel("福建队比赛数据.xlsx")# 从excel表格中定义x和y轴的数据y = df['比赛时间']x1 = df['主队得分']x2 = df['客队得分']# 设置文本为excel中的比赛时间labels = df['比赛时间']# 将画布规划为1×2的矩阵区域 , 依次在每个区域中绘制子图fig, (ax1, ax2) = plt.subplots(1, 2)barh1_rects = ax1.barh(y, x1, height=0.5, tick_label=labels, color='b')ax1.set_xlabel('得分')ax1.set_title('主队得分情况')ax1.set_xlim(0, x1.max() + 10)autolabel(ax1, barh1_rects)barh2_rects = ax2.barh(y, x2, height=0.5, tick_label=labels, color='r')ax2.set_xlabel('得分')ax2.set_title('客队得分情况')ax2.set_xlim(0, x2.max() + 10)autolabel(ax2, barh2_rects)# 调整子图之间的距离plt.tight_layout()plt.show()

(6)CBA福建队比赛主队得分和客队得分对比饼图

import pandas as pdimport matplotlib.pyplot as pltimport numpy as np# 处理中文乱码问题plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False#导入数据df = pd.read_excel("福建队比赛数据.xlsx")#从excel表格中定义x和y轴的数据x=df["比赛时间"]y_xf=df["主队得分"]y_qf=df["客队得分"]#设置文本为excel中的比赛时间labels=df["比赛时间"]#将画布规划成等分布局的2*1的矩阵区域,之后在索引为1的区域中绘制子图ax1=plt.subplot(211)#绘制饼图ax1.pie(y_xf,radius=1,wedgeprops={'width':0.5},labels=labels,autopct='%3.1f%%',pctdistance=0.75)ax1.set_title('主队得分情况',fontdict={'size':15})#将画布规划成等分布局的2*2的矩阵区域,之后在索引为3的区域中绘制子图ax1=plt.subplot(223)#绘制饼图ax1.pie(y_qf,radius=1,wedgeprops={'width':0.5},labels=labels,autopct='%3.1f%%',pctdistance=0.75)ax1.set_title('客队得分情况',fontdict={'size':15})#调整子图之间的距离plt.tight_layout()plt.show()

(7)CBA福建队比赛两队得分详情杠铃图

import pandas as pdimport matplotlib.pyplot as pltimport matplotlib.lines as mlines# 处理中文乱码问题plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False#读取数据df = pd.read_excel("福建队比赛数据.xlsx")df.sort_values('主队得分', inplace=True)df.reset_index(inplace=True)df = df.sort_values(by="index")def newline(p1, p2, color='black'): ax = plt.gca() # 获取当前的绘图区域 l = mlines.Line2D([p1[0], p2[0]], [p1[1],p2[1]], color='k') ax.add_line(l) return lfig, ax = plt.subplots(1, 1, figsize=(8, 6))# 绘制散点ax.scatter(y=df['index'], x=df['主队得分'], s=50, color='b', alpha=0.7,label="主队得分")ax.scatter(y=df['index'], x=df['客队得分'], s=50, color='r', alpha=0.7,label="客队得分")# 绘制线条for i, p1, p2 in zip(df['index'], df['主队得分'], df['客队得分']): newline([p1, i], [p2, i])ax.set_title("福建队得分详情", fontdict={'size':20})ax.set_xlim(50,150)ax.set_yticks(df['index'])ax.set_yticklabels(df['比赛时间'])# 设置x轴,y轴坐标标题ax.set_xlabel('得分')ax.set_ylabel('比赛时间')ax.grid(alpha=0.5, axis='x')#显示图例plt.legend(loc='upper right')plt.show()

四.总结

通过这一次的数据分析,我认识到爬虫数据的快速,但快速的同时,我们要进行数据清理,数据清理是我们收集数据源重要的部分。经过清理的数据,更加准确可靠。同时也让我更加熟悉了,pandas库、seaborn库、pyplot等方法的使用。本次分析的不足就是我对算法这方面的知识还不够了解,需更加努力地去学习。看到自己分析出来的数据可视化,很有成就感,可视化让数据变得不再那么文字冰冷,能更加生活形象地展示出这一段时间的数据,直关让人感受到数据的变化。期间实现可视化的过程中也经常存在一些报错问题。要有耐心,然后通过网上查找资料去不断解决问题。