技术菜鸟如何做出好看的奥运会奖牌榜
大家好,我是杰哥。
2021年7月23日,第32届夏季奥运会在日本东京拉开帷幕。大赛共设置33个大项50个分项339个小项,是历届奥运会中产生金牌最多的一届 。
中国队已88枚金牌、32枚银牌、18枚铜牌完美收官,我计划用可视化方法看一看历届奥运会奖牌榜。
数据准备
所有数据均是从维基百科中获取,有如下数据:
中国历年奥运奖牌榜成绩
▲ 中国历年奥运奖牌榜成绩
历届奖牌榜全球总榜
▲ 历届奖牌榜全球总榜
历届各国奖牌榜
中国历届单项比赛奖牌榜
可视化
历年主办国分布图
夏季奥林匹克运动会(Summer Olympic Games或Games of the Olympic)是由国际奥林匹克委员会主办的国际性多项运动赛事,每四年举办一次。从1904年起,夏季奥运会的每个项目都会颁发奖牌,其中第一名为金牌,第二名为银牌,第三名为铜牌。
美国举办过4次夏季奥运会,是举办奥运会次数最多的国家。英国于2012年第3次举办夏季奥运会,伦敦成为第1个举办3次夏季奥运会的城市。澳大利亚、法国、德国、日本和希腊都举办过2次夏季奥运会。
其他举办过夏季奥运会的国家有:中国、比利时、加拿大、芬兰、意大利、墨西哥、荷兰、韩国、西班牙、苏联和瑞典。亚洲第1次奥运会在日本东京举办。南美洲的第1次奥运会在巴西里约热内卢举办。有5个城市曾2次举办过夏季奥运会:东京、洛杉矶、伦敦、巴黎和雅典。
绘图方法
绘图工具:pyecharts + Microsoft
第一步,利用pyecharts绘制主办国及主办次数全球地图可视化,可以直接到官网例子学习如何绘制一个全球图。
第二步,为地图标上带箭头的时间文字,由于暂未习得如何在pyecharts地图上用代码的方法实现标注,因此可以借助Microsoft手动标注。
from pyecharts import options as opts
from pyecharts.charts import Map
df_1 = df_total.groupby(['country']).count().reset_index()
c = (
Map()
.add("", [list(z) for z in zip(df_1.country, df_1.年份)], "world",is_map_symbol_show=False)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="数据STUDIO"),
visualmap_opts=opts.VisualMapOpts(max_=4,is_show=False),
)
# .render("map_world.html")
)
c.render_notebook()
历届奖牌榜
奥运会是全世界规模最大的综合性体育运动会,全世界的各个国家都会派运动员来参加!奥运会五大体育强国:1.美国,2.中国,3.英国,4.法国,5.德国。
截至里约奥运会,中国代表团共参加过九届夏季奥运会,累计取得546枚奥运奖牌,包括224枚金牌 、167枚银牌、155枚铜牌。
绘图方法
上图是按照金牌总数金牌排序绘图,由于参赛国家过多,这里只绘制了金牌总数TOP30的国家。
绘图工具:Plotly + Microsoft
第一步通过以下代码绘制堆叠柱状图,第二步将国旗图片与柱状图组合。
df_total_country_num = df_total_country.iloc[:30,].iloc[::-1,:]
fig = go.Figure()
fig.add_trace(go.Bar(
x=df_total_country_num['金'],
y=df_total_country_num['国家'],
name='金牌',
orientation='h',
marker=dict(
color='rgba(242,192,86, 0.6)',
line=dict(color='rgba(242,192,86, 1.0)', width=3)),
textposition='inside',
text=df_total_country_num['金'].values,
textangle = 90))
fig.add_trace(go.Bar(银牌))
fig.add_trace(go.Bar(铜牌))
fig.update_layout(barmode='stack', height=1000,
width=1000,
title='历届奖牌榜TOP30',
template='ggplot2',
font=dict( size=12, color="Black" ),
plot_bgcolor="#fafafa",
legend=dict(yanchor="top",
y=1.1, xanchor="left", x=0.9))
fig.show()
中国历年奥运奖牌榜成绩
翻阅新中国夏季奥运会历史,最早可上溯到1984年。中国在重返国际奥委会后首次派出代表团参加夏季奥运会。
1988年,乒乓球项目首次进入夏季奥运会,中国夺得了4枚金牌中的2枚,奠定了在该项目中不可动摇的地位。
1992年,巴塞罗那夏季奥运会上,中国代表团在田径、柔道中实现突破 。
1996年,亚特兰大奥运会上,首次实现了乒乓球项目的金牌包揽。
2000年,悉尼奥运会上,中国代表团在乒乓球项目再度实现对金牌的包揽,举重、体操、跳水、羽毛球等项目也收获颇丰,并获得了中国队在跆拳道项目的首枚金牌。
2004年,雅典奥运会,中国队在网球、摔跤和皮划艇比赛中首次有金牌入账,刘翔在男子110米栏比赛中为中国队取得历史上首枚男子径赛奥运金牌,成为国人的骄傲。
2008年,中国的首都北京成为奥运会主办国,中国取得了51金21银28铜的优异成绩,成为奥运历史上首个登上金牌榜首的亚洲国家。
2012年,第30届奥运会在英国伦敦举行。羽毛球跟随乒乓球其后,成为中国队第二个实现金牌包揽的项目。
2016年,第31届里约奥运会上,中国队不仅在乒乓球、跳水等传统优势项目上争金夺银,而且在场地自行车项目中首次拿到金牌。中国女排暨1984、2004年两度夺冠以来,再次登顶,续写女排精神的荣耀。
相对于体育强国美国而言,中国近年来一路逆袭,无时无刻不在诠释着中国的奥运精神。
绘图方法
绘图工具:Plotly
fig = go.Figure()
fig.add_trace(go.Bar(
x=df_total_year['地点'],
y=df_total_year['金牌'],
name='金牌',
marker_color='gold',
textposition='inside',
text=df_total_year['金牌'].values,
textangle = 90
))
fig.add_trace(go.Bar('银牌'))
fig.add_trace(go.Bar('铜牌'))
fig.add_trace(go.Scatter(
x=df_total_year['地点'],
y=df_total_year['参赛选手'],
name='参赛选手',
mode='markers+text+lines',
marker_color='black',
marker_size=10,
textposition='top center',
line=dict(color='orange',dash='dash'),
yaxis='y2'))
fig.update_layout(barmode='group', xaxis_tickangle=-45,
title='中国历年奥运奖牌榜成绩',
xaxis_title="主办国",
yaxis_title="奖牌数",
template='ggplot2',
font=dict(size=12, color="Black"),
xaxis=dict(showgrid=False),
yaxis=dict(showgrid=False),
plot_bgcolor="#fafafa",
yaxis2=dict(showgrid=True,overlaying='y',side='right',title='参赛选手'),
legend=dict(yanchor="top",
y=1.3, xanchor="left", x=0.9))
fig.show()
单项比赛项目成绩表
从比赛项目来看,跳水、举重、体操、乒乓球、射击、羽毛球是中国传统的优势体育项目。其中,跳水更是以40枚金牌成为了中国获得最多金牌的奥运项目。
绘图方法
绘图工具:Excel
直接选中数据,插入条形图,并设置数据点格式,用目标图片对其进行填充(图片或纹理填充),填充方式为层叠。
酷炫的全球奖牌分布动图
绘图方法
绘图工具:geopandas + imageio
第一步,先利用geopandas绘制出历年各个奖牌的全球分布图,其中比较影响美观的参数:cmap,根据matplotlib颜色集选取合适的颜色,以达到美观的效果。
第二步,将上面绘制出的png静态图,通过imageio将其合成动态图,可以看到奖牌榜分布随着时间的变化情况。
地图绘制代码
import geopandas
import matplotlib.colors
import pycountry
import matplotlib.pyplot as plt
def alpha3code(column):
CODE=[]
for country in column:
try:
code=pycountry.countries.get(name=country).alpha_3
CODE.append(code)
except:
CODE.append('None')
return CODE
def draw_geo(geo_temp,col,kind,name,name2,cmap='Set3'):
geo_temp['CODE']=alpha3code(geo_temp['English'])
vmin = 0
vmax = 40
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
world.columns=['pop_est', 'continent', 'name', 'CODE', 'gdp_md_est', 'geometry']
merge=pd.merge(world,geo_temp,on='CODE')
ax = world.plot(figsize=(20,15), linewidth=0.25, edgecolor=background_color, color='lightgray')
ax.axis('off')
# ax.set_facecolor(background_color)
merge.plot(column=col,figsize=(20, 15),cmap=cmap,ax=ax, legend=True,
legend_kwds={'shrink': 0.5},vmin=vmin, vmax=vmax)
ax.text(-175,112,f'{name}年{name2}奥运会',
fontsize=30,fontweight='bold',color='#323232')
ax.text(-175,102,f'{kind}牌总数',
color='gray',fontsize=20)
plt.show()
plt.savefig(fname=f'{name}.png')
Gif动图合成代码
import imageio
def create_gif(image_list, gif_name, duration = 2):
"""
生成Gif文件,原始图像仅仅支持png格式
image_list : 输入图像的路径
gif_name : 字符串,所生成的gif文件名,带.gif文件名后缀
duration : gif图像时间间隔,这里默认2s
"""
# 创建一个空列表,用来存源图像
frames = []
# 利用方法append把图片挨个存进列表
for image_name in image_list:
frames.append(imageio.imread(image_name))
# 保存为gif格式的图
imageio.mimsave(gif_name, frames, 'GIF', duration = duration)
return
def main(name):
image_list = ['1984.png','1988.png','1992.png','1996.png','2000.png',
'2004.png', '2008.png', '2012.png','2016.png']
gif_name = f'{name}.gif'
duration = 1.5
create_gif(image_list, gif_name)
参考资料
[1] 奥运会logo图片及数据来源维基百科: https://zh.wikipedia.org/wiki/夏季奥林匹克运动会
[2] 奥运历史资料:https://baijiahao.baidu.com/s?id=1706677041934937288&wfr=spider&for=pc