谁才是真正的体育强省!?用python带你一览2021陕西全运会数据找答案!

562 阅读10分钟

大家好,我是才哥。

我们知道全宇宙最顶级的综合性运动会,也就是中华人民共和国全国运动会,今年在陕西开展的是第14届。1万多名来自全国各地的运动健儿在这里进行角逐,正好我们可以透过这次比赛的数据来看看谁才是咱们真正的体育强省

让我们一起来看看吧~

1. 数据采集

全运会有个低调的官网,里面有非常详尽的数据,我这边用python直接从该网站采集了本届的各类数据,采集过程不做详细介绍了,大家看代码即可。

第十四届全运会信息发布系统:

info.2021shaanxi.com/

第十四届全运会信息发布系统

1.1. 比赛大项数据

比赛大项数据是指官网展示的一共49项大的比赛项目数据,主要包含项目ID项目名称

import requests
import pandas as pd

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36",
    }
# 大项
url = 'https://info.2021shaanxi.com/Data/commonCode/disciplineList.json'

r = requests.get(url, headers= headers)

data = r.json()
 
disciplineList = pd.DataFrame(data)
disciplineList.replace(r'-','',regex=True,inplace=True)
disciplineList.sample(5)

大项预览

1.2. 比赛小项数据

比赛小项是指具体的比赛项目,比如大项射箭—男子—男子反曲弓个人项目,本次一共有427个小项。

# 小项
url = 'https://info.2021shaanxi.com/Data/commonCode/event.json'

r = requests.get(url, headers= headers,)

data = r.json()

items = []
for key in data.keys():
    for key1 in data[key].keys():
        item = data[key][key1][0]
        items.append(item)

event = pd.DataFrame(items)
event.replace(r'-','',regex=True,inplace=True)
event.sample(5)

小项

1.3. 代表团数据

代表团是指省、机构组织或者个人,比如北京市、湖北省,北京体育大学组织或者个人(如游泳、山地车等就有以个人名义参加的运动员),一共58个代表团组织。

# 代表团
url = 'https://info.2021shaanxi.com/Data/commonCode/delegation.json'

r = requests.get(url, headers= headers, )

data = r.json()

items = []
for key in data.keys():
    item = data[key][0]
    items.append(item)

delegation = pd.DataFrame(items)
delegation.replace(r'-','',regex=True,inplace=True)
delegation.sample(5)

代表团

1.4. 运动员数据

运动员一共12434人,但实际有参与项目的12037人。

# 运动员
items = []
for Id in disciplineList['Id']:
    url = f'https://info.2021shaanxi.com/api/participant/list?discipline={Id}'
    r = requests.get(url, headers= headers)

    data = r.json()
    item = data['data']
    items.extend(item)
    
AthleteList = pd.DataFrame(items)
AthleteList.replace(r'-','',regex=True,inplace=True)    
AthleteList['event_count'] = AthleteList.EventEntry.apply(len)    
# 匹配大项
AthleteList = AthleteList.merge(disciplineList[['Id', 'CHI_Description']],
                                right_on='Id', left_on='DisciplineCode', how='left')
# 匹配组织
AthleteList = AthleteList.merge(delegation[['Id', 'CHI_Description']], 
                                left_on='OrganisationCode', right_on='Id', how='left')
AthleteList.sample(5)

运动员

1.5. 决赛名次数据

决赛名次其实就是每个项目比赛结果数据,金银铜牌获得者的信息,后续我们可以根据这份数据来看看体育强省在哪里!

# 决赛数据
dataList = []
# 决赛日期(数据是9-25号采集的,所以截止选的9-24日)
dateList = pd.date_range('2021-07-12','2021-09-24').strftime('%Y%m%d')

for date in dateList:
    url = f'https://info.2021shaanxi.com/Data/Medal/Daily/{date}/data.json'
    
    r = requests.get(url, headers= headers)
    try:
        data = r.json()
        
        data = pd.DataFrame(data)
        data.replace(r'-','',regex=True,inplace=True)
        
        def get_BirthDate(x):
            if len(x)==1:
                return x[0]['BirthDate']

        def get_AthleteCode(x):
            if len(x)==1:
                return x[0]['AthleteCode']
            
        data['BirthDate'] = data['Members'].apply(get_BirthDate)
        data['AthleteCode'] = data['Members'].apply(get_AthleteCode)
        dataList.append(data)
    except :
        continue
data = pd.concat(dataList)

df = data[['Date', 'EventCode', 'MedalRank', 'OrganisationCode', 'Gender',
          'Name', 'BirthDate', 'AthleteCode']]
# 匹配组织
df = df.merge(delegation[['Id', 'CHI_Description']], 
              left_on='OrganisationCode', right_on='Id', how='left')
# 匹配小项
df = df.merge(event[['CHI_Description','Code', 'Discipline', 'Team_Event']],
              right_on='Code', left_on='EventCode', how='left')
# 匹配大项
df = df.merge(disciplineList[['Id', 'CHI_Description']],
              right_on='Id', left_on='Discipline', how='left')
# 字段筛选
df = df[['Date', 'CHI_Description', 'CHI_Description_y', 'Gender', 'MedalRank', 
         'Name', 'CHI_Description_x','BirthDate', 'AthleteCode', 'Team_Event']]
df.sample(5)

决赛名次

2. 统计展示

本部分我们将进行项目统计代表团(尤其是省级行政区代表团)统计以及运动员统计三部分展开。

2.1. 项目维度

本届全运会大项目一共49个,小项目一共427个,具体分布如下:

大项-小项分布

田径游泳是拥有小项最多的,其中田径的小项高达52种、游泳的小项也有高达37种。热度较高的跳水小项也很多有17种,乒乓球则有7种小项。

分布箱线图

# 筛选全小项
event = event[(event['Event'].str.len()>0)&(event['Gender'].str.len()>0)]
# 匹配大项名称
Discipline_event_Num = event.merge(disciplineList, left_on='Discipline', right_on='Id').groupby('CHI_Description_y')['Code'].nunique().to_frame('小项数')
Discipline_event_Num.sort_values(by='小项数', ascending=False).reset_index()

大项-小项分布 前10

各大项参与人数

田径足球是参与人数最多的项目,都多达1000人以上。不过,大多数的团体项目参与人数都是较多的无疑了。

# 各项目运动员数
Discipline_Num = AthleteList.groupby('CHI_Description_x')['AthleteCode'].nunique().to_frame('人数')
Discipline_Num.sort_values(by='人数', ascending=False).reset_index()

各项目参赛人数

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

# 设置柱状图颜色
colors = ['turquoise', 'coral']

labels = Discipline_Num.index
y = Discipline_Num['人数']

x = np.arange(len(labels))  
width = 0.35  

fig, ax = plt.subplots(figsize=(8,16))
rects1 = ax.barh(x + width/2, y, color=colors[1], edgecolor='grey')

ax.set_title('各项目参赛人数', fontsize=16)
y_pos = np.arange(len(labels))
ax.set_yticks(y_pos)
ax.set_yticklabels(labels, fontsize=12)

# 显示数据标签
ax.bar_label(rects1, padding=3)

fig.tight_layout()
# 边框隐藏
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
plt.show()
fig.savefig('各项目参赛人数.png')

个人团体分布

在全部小项目中有139项约占32.6%的项目是团体类的(比如足球、乒乓球混双等),另外288项占比67.54的项目是个人赛

个人团体分布

# 个人团体分布 (Discipline)
Team_Event_Num = event.groupby('Team_Event')['Code'].nunique().to_frame('小项数')
labels = Team_Event_Num.index
sizes = Team_Event_Num['小项数']
explode = (0,  0.1,) 

fig1, ax1 = plt.subplots(figsize=(6,5))
patches, texts, autotexts = ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
                                    shadow=True, startangle=90)
ax1.axis('equal') 
ax1.set_title('各比赛小项个人团体分布', fontsize=16)
# 重新设置字体大小
proptease = fm.FontProperties()
proptease.set_size('large')
plt.setp(autotexts, fontproperties=proptease)
plt.setp(texts, fontproperties=proptease)

plt.show()

性别分布

207个项目是男性项目,193个项目是女性项目,混合类的有21种,而不分男女共6种(马术比赛)

性别分布

# 性别分布 
Gender_Event_Num = event.groupby('Gender')['Code'].nunique().to_frame('小项数')
labels = Gender_Event_Num.index
sizes = Gender_Event_Num['小项数']
explode = (0,  0., 0, 0, ) 

fig1, ax1 = plt.subplots(figsize=(8,7))
patches, texts, autotexts = ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
                                    shadow=True, startangle=90)
ax1.axis('equal') 
ax1.set_title('各比赛小项性别分布', fontsize=16)
# 重新设置字体大小
proptease = fm.FontProperties()
proptease.set_size('large')
plt.setp(autotexts, fontproperties=proptease)
plt.setp(texts, fontproperties=proptease)

plt.show()

2.2. 代表团维度

一共58个代表团,其中34个省级行政区+4个协会、13个俱乐部、2个学校等,其中OO是联合队(奥运会联合队)

各类代表团分布

Type数量
0D38
1CLUB13
2RO3
3SCHOOL2
4GR1
5OO1
# 代表团类型
Type_delegation_Num = delegation.groupby('Type')['Id'].nunique().to_frame('数量')
Type_delegation_Num.sort_values(by='数量', ascending=False).reset_index()

代表团类型分布

代表团人数对比

虽然说有58个代表团,实际参赛的代表团53个,比如我们的台湾省并没有参与,希望他们能早日参与进来。在这53个代表团中,我们按照省级行政区和其他分类对比看看。

省级行政区

山东、广东、江苏、上海陕西是本次参数选手最多的省份

各省份参赛人数

其他

天津体育学院作为高校,有24名参数选手,北京体育大学则有2名。

其他代表团参赛人数

代表团参与大项数

作为东道主的陕西,本届全运会参与了高达47/49个大类,此外参赛人数较多的江苏、广东和上海均参加了44个大类。

Organisation_Discipline_Num = AthleteList.groupby('CHI_Description_y')['CHI_Description_x'].nunique().to_frame('大项数')
Organisation_Discipline_Num.sort_values(by='大项数', ascending=False).reset_index()

代表团参与大项数

代表团奖牌数

注:后续章节数据截止时间为9月24日24点。。

在总奖牌数排名中,山东广东、江苏、浙江上海高居前列(这联合队未进行细分到省份哈)

Organisation_Medal_Num = df.pivot_table(values='Name',margins=True,index='CHI_Description_x',columns='MedalRank',aggfunc='count').fillna(0)
Organisation_Medal_Num = Organisation_Medal_Num.sort_values(by='All', ascending=False).reset_index()
Organisation_Medal_Num.columns = ['代表团','金牌','银牌','铜牌','总奖牌']
Organisation_Medal_Num.convert_dtypes()
代表团金牌银牌铜牌总奖牌
0All3313313911053
1山东353835108
2广东302648104
3江苏27273185
4浙江25252878
5上海16192358
6四川14172051
7陕西16132049
8福建18151649
9湖北12161543
10联合队354140
11辽宁7131737
12北京10121234
13天津881632
14河北8101331
15河南1081331
16湖南1311731
17安徽69924
18山西471021
19内蒙古74718
20云南57517
21江西26513
22广西26412
23吉林23712
24新疆25310
25甘肃2439
26贵州2259
27重庆1629
28黑龙江1449
29香港1056
30前卫体协2215
31海南4105
32西藏3025
33青海0314
34贵州轮迹自行车运动俱乐部1012
35火车头体协0011
36澳门0011

代表团夺金数(金牌榜)

金牌榜中,山东最强,其次是联合队,接着依次是广东、江苏、浙江和福建

我们发现联合队基本都是金牌,这也是为什么本届的奥运联合队会机制会被网友吐槽的原因!

排名代表团金牌银牌铜牌总奖牌
1山东353835108
2联合队354140
3广东302648104
4江苏27273185
5浙江25252878
6福建18151649
7上海16192358
8陕西16132049
9四川14172051

2.3. 运动员维度

这部分我们主要看看运动员年龄分布,感受一下咱们新生代力量。

我们一共有668名运动员获得了奖牌,其中金牌获得者208人,银牌获得者215人,铜牌获得者270人。

注意:本部分不考虑团体赛

参数运动员性别分布

全部参赛选手中,男性占比52.2%,女性占比47.8%,总的来说是非常平衡的了。

参数运动员性别分布

# 参赛选手性别分布
Gender_Num = AthleteList.groupby('GenderCode')['AthleteCode'].nunique().to_frame('人数')

奖牌最多的运动员

个人单项赛事奖牌最多的有5个人,均为3块奖牌

运动员性别金牌银牌铜牌总奖牌
1汪顺M3003
2张子扬M2103
3王春雨W2103
4季新杰M1203
5覃海洋M1113
Athlete_Medal_Num = df[df['Team_Event']=='N'].pivot_table(values='CHI_Description',margins=True,index=['Name','Gender'],columns='MedalRank',aggfunc='count').fillna(0)
Athlete_Medal_Num = Athlete_Medal_Num.sort_values(by=['All',1,2,3], ascending=[False,False,False,False]).reset_index()
Athlete_Medal_Num.columns = ['运动员','性别','金牌','银牌','铜牌','总奖牌']
Athlete_Medal_Num.convert_dtypes().head()

那都是通过什么项目获得的呢?

来自田径和游泳

3块奖牌获得者

nameList = Athlete_Medal_Num[Athlete_Medal_Num['总奖牌']>=3]['运动员']
df[df['Name'].str.contains('|'.join(nameList))].sort_values(by = 'Name')

事实上,来自浙江的1994年的汪顺已经收获了含团体赛在内的6枚金牌!

汪顺

金牌最多的运动员

金牌数最多的就是上面那个汪顺

同样获得金牌最多的女子则是王春雨,田径选手来自安徽的1995年跑步健将!

王春雨

获奖运动员年龄分布

本届全运会,大部分的获奖运动员出生年份集中在1994年-2000年

我们发现居然还有1971年的51岁选手!!,最小的则是2008年的13岁朋友!!相差接近4倍~

获奖运动员年龄分布

时隔12年 “七战”1971年的老将刘英姿再夺全运会飞碟多向金牌

出生1971年选手

2008年出生的小奖,有三个是青年组的选手。

出生于2008年的选手

金牌运动员年龄分布

1996年和2000年出生的金牌运动员最多,居然刚好差了4年(一届周期)

金牌运动员年龄分布

以上就是本次全部内容,感兴趣的朋友可以后台回复 955 在 全运会文件夹里获取 案例数据和演示文件。

其实,还有很多维度和展现形式,更加全面的呈现本届全运会全貌,以及更好的了解体育强省,期待你的作品!