1896-2021历届奥运会奖牌榜动态排序(Matplotlib图表动画)
摘 要
在制作动态排序动画之前,我们看一下数据的整理情况:
a、对第1)种大部分数据的情况,先爬取下来,输出到excel(1);
b、对第2)种小部分数据的情况,也先爬取下来,输出到另一个excel(2);
c、对第3)种个别的,还有第31-32届的数据,算了,别折腾了,手动复制粘贴到excel(3)吧。
d、最后把这3个excel合并到一个excel,进行数据处理吧。
二、数据处理
经过-历届奥运会奖牌榜动态排序系列的数据处理(第二篇),我们得到了a数据:
看到这张数据表,还有以下几点需要调整:
1、合并3个excel数据;
2、标题、年份列顺序调整到名次前;
3、'国家'列名修改为'国家/地区';
4、计算奖牌的合计数量;
5、根据年份,计算各国的奖牌合计数排名。
1)合并DataFrame:concat(),合并函数还有merge、join函数,有兴趣可以进入以下链接进行学习()
df1 = pd.read_excel("./data/Olympic10.xlsx") df2 = pd.read_excel("./data/Olympic11.xlsx") df3 = pd.read_excel("./data/Olympic12.xlsx") df = pd.concat([df1,df2,df3],axis=0,ignore_index=True,sort=True)
2)调账列顺序
columns = ['标题','年份','国家','金牌','银牌','铜牌'] df = pd.DataFrame(df, columns=columns)
3)列名修改
df.rename(columns={'国家':'国家/地区'},inplace=True)
4)计算奖牌合计
df['合计'] = '' df['合计'] = df['金牌'] + df['银牌'] + df['铜牌']
5)按年份,计算各国的奖牌合计数排名
df['排名'] = df.groupby('年份',axis=0)['合计'].rank(method='first',ascending=False)
另外,再对数据进行一些微调
df=df.drop_duplicates(subset=['年份', '国家/地区'], keep='first') df.sort_values(["年份","排名"],inplace=True,ascending=True) #将国家/地区列字符串中的空格都去除 df['国家/地区'].replace('\s+','',regex=True,inplace=True)
最终获得我们的完整数据
df.to_excel("./data/Olympic_final.xlsx")
完整代码如下:
import pandas as pd df1 = pd.read_excel("./data/Olympic10.xlsx") df2 = pd.read_excel("./data/Olympic11.xlsx") df3 = pd.read_excel("./data/Olympic12.xlsx") df = pd.concat([df1,df2,df3],axis=0,ignore_index=True,sort=True) columns = ['标题','年份','国家','金牌','银牌','铜牌'] df = pd.DataFrame(df, columns=columns) df.rename(columns={'国家':'国家/地区'},inplace=True) df['合计'] = '' df['合计'] = df['金牌'] + df['银牌'] + df['铜牌'] df.loc[df['年份']==,'年份'] = df=df.drop_duplicates(subset=['年份', '国家/地区'], keep='first') df['排名'] = df.groupby('年份',axis=0)['合计'].rank(method='first',ascending=False) df.sort_values(["年份","排名"],inplace=True,ascending=True) #将国家/地区列字符串中的空格都去除 df['国家/地区'].replace('\s+','',regex=True,inplace=True) df.to_excel("./data/Olympic_final.xlsx")
输出结果:
三、动态排序
经过一系列的数据处理,终于可以验证下劳动成果了。完整代码如下:
import pandas as pd import random import matplotlib.pyplot as plt import matplotlib.ticker as ticker import matplotlib.animation as animation from IPython.display import HTML import matplotlib plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签 plt.rcParams['axes.unicode_minus']=False #这两行需要手动设置 #防止动漫内存太大,报错 matplotlib.rcParams['animation.embed_limit'] = 2**128 def randomcolor(): colorlist = ['1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'] color ='' for i in range(6): color += random.choice(colorlist) return '#'+ color df = pd.read_excel(./data/Olympic_final.xlsx") #对地区列表进行去重,分类; area_list1 = set(df['国家/地区']) # color_list用于存放随机生成颜色代码个数 # 因为后面区域个数 要与颜色个数保持一致,这里用了len函数; color_list =[] for i in range(len(area_list1)): str_1 = randomcolor() color_list.append(str_1) str_1 = randomcolor() #area_list转化为列表 area_list_1 = [i for i in area_list1] #colors表示 所在城市:颜色 一一对应字典形式; colors =dict(zip(area_list_1,color_list)) # 用plt加理图表,figsize表示图标长宽,ax表示标签 fig, ax = plt.subplots(figsize=(15, 8)) #dras_barchart生成current_year这一年各城市人口基本情况; def draw_barchart(current_year): #dff对year==current_year的行,以”合计“降序排序,取前十名; dff = df[df['年份'].eq(current_year)].sort_values(by='合计',ascending = True).tail(10) # 所有坐标、标签清除 ax.clear() #显示颜色、城市名字 ax.barh(dff['国家/地区'],dff['合计'],color = [colors[x] for x in dff['国家/地区']]) dx = dff['合计'].max()/200 #ax.text(x,y,name,font,va,ha) # x,y表示位置; # name表示显示文本; # va,ba分别表示水平位置,垂直放置位置; for i ,(value,name) in enumerate(zip(dff['合计'], dff['国家/地区'])): ax.text(value-dx,i,name,size=18,weight=600,ha ='right',va = 'bottom',color='#77') ax.text(value+dx,i ,f'{value:,.0f}',size = 14,ha = 'left',va ='center') #ax.transAxes表示轴坐标系,(1,0.4)表示放置位置 ax.text(1,0.4,current_year,transform = ax.transAxes,color ='#77',size = 46,ha ='right',weight=800) ax.text(0,1.06,'Olympic Medals',transform = ax.transAxes,size=12,color='#77') #set_major_formatter表示刻度尺格式; ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}')) ax.xaxis.set_ticks_position('top') ax.tick_params(axis='x',colors='#77',labelsize=12) ax.set_yticks([]) #margins表示自动缩放余额; ax.margins(0,0.01) # 设置后面的网格 ax.grid(which='major',axis='x',linestyle='-') #刻度线和网格线是在图标上方还是下方,True为下方 ax.set_axisbelow(True) ax.text(0,1.15,'历届奥运会奖牌排行榜', transform=ax.transAxes,size=24,weight=600,ha='left',va='top') ax.text(1,0,'Officetouch制作',transform = ax.transAxes, size=16,color ='#77',ha = 'right', bbox = dict(facecolor='white',alpha = 0.8,edgecolor='white')) #取消图表周围的方框显示 plt.box(False) #draw_barchart() #将原来的静态图拼接成动画 fig, ax = plt.subplots(figsize=(15, 8)) animator = animation.FuncAnimation(fig, draw_barchart, frames=df['年份'].drop_duplicates(),interval = ) animator.save("./data/Olympic.gif", writer='pillow')
输出结果:
结 语
学习需要耐心和时间的投入,初学的时候可能需要投入比较多的时间和精力,但只要有这样一个过程,你就会脱胎换骨,一点一滴的积累成就自己。
1、数据采集-爬虫;
Bertram Xu:-历届奥运会奖牌动态排序动画(Python数据采集)2、数据处理-数据清洗;
Bertram Xu:-历届奥运会奖牌榜(Python数据处理)3、数据动态排序。(本篇文章)
因为奥运数据连续性较差,如果我们分析一些连续性强的数据,如各国人口数据,动态排序的效果会好很多。
最全的历年奥运会金牌排行榜汇总
年夏季奥林匹克运动会,是第一届现代奥林匹克运动会,也是自罗马帝国皇帝狄奥多西一世在公元393年废除古代奥运会以来的首届奥运会,至今刚好满120年。
在过去的30届奥运会中,每一届前10名的国家有哪些,分别获得了多少金牌?稳赚理财助手为您列出了最全的奥运会金牌名单,跨度120年哦~
历届奥运奖牌榜前十,体育强国继续霸榜,荷兰取代韩国入榜
历届奥运奖牌榜前十,体育强国继续霸榜,荷兰取代韩国入榜。年东京奥运会圆满落幕,中国奥运代表团表现出色,排在奖牌榜第二位,在奥运比赛日最后一天被美国反超。本届奥运会中国奥运代表团获得了38金,32银,18铜,总奖牌数88枚的好成绩。美国队由于田径、游泳等金牌大项优势明显,再加上球类项目又安排在奥运会最后阶段,因此被他们反超也是可以预见的,不过这次竞争非常激烈,只相差1枚金牌。值得注意的是,奖牌榜的前十名,依然是体育强国继续霸榜,下面我们通过最近四届奥运会来分析一下奖牌榜的排名情况。
本届东京奥运会,与以往3届奥运会有几个不同之处。第一,总金牌数没有超过40枚的国家;第二,排名前五的国家金牌数都上了20枚,这在以往的奥运会中是没有出现过的情况;第三,奥运奖牌榜前十都有10枚或以上的金牌。从以上的数据可以看出,奥运金牌榜前五的竞争非常激烈,体育强国的竞争力更强了。但是有一点却出人意料,在最近4届奥运会中,我们的邻国韩国都进入了奖牌榜前十,但是本届奥运会却遭遇了滑铁卢,他们最终只获得了6枚金牌,最终排在加拿大、巴西、新西兰、古巴、和匈牙利之后,仅获得了第16名。韩国的滑落或许是他们竞争力的减弱,或许是与东道主紧张的关系有关,原因应该是多方面的。
下面我们来回顾一下最近3届奥运会奖牌榜的情况。先来看年北京奥运会,我们国家作为东道主,获得了51金,21银,28铜的好成绩,位居奖牌榜第一名。美国、俄罗斯分列第二、三位。从历届奥运会来看,东道主获得好成绩成为普遍现象,比如此次日本就获得了前所未有的好成绩,他们获得了27枚金牌,是年奥运会的3倍;此外,他们的女子篮球实力一般,也获得了奥运会的银牌,这些都是东道主的优势。
再来回顾一下年伦敦奥运会的奖牌榜。伦敦奥运会排名第一的是美国队,他们在这届奥运会中获得了46金,29银,29铜,总奖牌数104枚。排在第二的是中国奥运代表团,获得了38金,27银,23铜的好成绩。排名第三的是东道主英国,他们获得了29金,17银,19铜。排名第7-10名的国家分别是:俄罗斯、韩国、德国、法国、意大利、匈牙利、澳大利亚。
距离年东京奥运会最近的一届奥运会是年里约奥运会。这届奥运会中国奥运代表团的成绩不是很理想,只获得了26枚金牌,18枚银牌,26枚铜牌,排在奖牌榜第3名。排名第一的是美国,他们获得了46金,37银,38铜。英国以27金,23银,17铜排在第三。排名前十的其他国家分别是:俄罗斯、德国、日本、法国、韩国、意大利、澳大利亚。
从最近4届奥运会奖牌榜前十的情况来看,体育强国之间的竞争越来越强烈了,尤其是前三名之间的争夺,反复换位。根据目前的形式和发展来看,未来一段时间中美之间争夺奖牌榜第一名将长期存在。而前十名还是以:中国、美国、俄罗斯、英国、德国、法国、日本、意大利、澳大利亚、韩国、荷兰等体育强国为主。从本届奥运会来看,韩国的滑落或许与日本的紧张关系有关,或许与他们的优势项目有关,但是荷兰的崛起应该不是偶然现象,他们在将来可能继续竞争奥运奖牌榜前十。
奥与会秉承更快、更高、更强、更团结的口号,希望把这种精神保持下去,让各国选手在公平的环境下进行比赛,这样才能更好地把奥运精神延续下去,我们不希望看到为了获得更多的金牌而有失公平。
1896-2021历届奥运会奖牌榜(Python数据处理)
阅读本文大约需要 3 分钟摘 要
这两天在平台上看到一些创作者失去创作动力的感慨,OF只想说往事如昙花一现,我们都需要时刻静下心来,认真地考虑下自己的创作目标并付诸行动。遥想当年OF做软件系统的时候,开源社区还没有像现在这样健全。再看看如今,衷心感谢创作者们孜孜不倦地分享,建立了一个良好的创作氛围。说不定再写几年,也可以出本书啥的。
主要内容:Excel 办公自动化和数据分析
适用人群:办公室职员 / Python 初学者 / 有志从事数据分析工作的人员
准备内容:Anaconda-Spyder;re、Pandas库
二、数据处理
言归正传,上篇OF介绍了运用数据爬虫获取到了历届奥运会的奖牌数据
观察下这些数据,先列出需要改善的点:
1、知识点1去掉空格:替换replace()str.replace(正则式/字符串,替换的目标字符)
#将国家列字符串中的空格都去除 df['国家'].replace('\s+','',regex=True,inplace=True) 2、知识点2删除多列空值的行:删除dropna()
df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
参数说明:
axis:默认为 0,表示逢空值剔除整行,如果设置参数 axis=1 表示逢空值去掉整列。how:默认为 'any' 如果一行(或一列)里任何一个数据有出现 NA 就去掉整行,如果设置 how='all' 一行(或列)都是 NA 才去掉这整行。thresh:设置需要多少非空值的数据才可以保留下来的。subset:设置想要检查的列。如果是多个列,可以使用列名的 list 作为参数。inplace:如果设置 True,将计算得到的值直接覆盖之前的值并返回 None,修改的是源数据。当金牌、银牌、铜牌都为空时,我们可以删除该行,用dropna(thresh=1)就是保留至少1个非空值的数据可以保留,那我们想办法先把其他列数据都置空,再判断每行只要有一个数据就保留
cols=['金牌','银牌','铜牌'] #df[cols]!="" 判断3列数据各是True or False #df[df[cols]!=""] 呈现所有列数据,只留下3列数据,其他列都置空 #df[df[cols]!=""].dropna(thresh=1).index 保留至少有1个非空值的行集合3、知识点3删除含有XX内容的行:-df[].isin([])
当我们进行数据处理时,最重要的是学会找规律,用最简单的方法实现我们想要达到的效果,比如我们看到的问题是要把奖牌都为中文的行删除,我们同时可以观察到,这些行的名次列都是“名次”
#删除原中文标题(名次列为"名次"的行删除) df = df[-df["名次"].isin(["名次"])]4、知识点4通过条件找其他列数据并删除
1)我们的条件是:非数字行,首先筛选['名次']列中非数字行
2)找到的某列数据会有很多重复,我们可以进行去重处理drop_duplicates()
3)最后对含该列的数据进行删除
#筛选列中非数字的行 a = df[['名次']].apply(pd.to_numeric, errors='coerce').notnull().all(axis=1) #筛选列中不为数字的行对应的标题名称 title_list = df.loc[a==False,"标题"].drop_duplicates() #删除标题列中含有title_list内容的行 df = df[-df["标题"].isin(title_list)]5、知识点5多个字符替换:replace({})
df.replace({'-':'0','–':'0','_':'0'},inplace=True)6、知识点6替换空值为'0':fillna()
df.fillna('0', inplace=True) 7、知识点7修改列的数据类型:astype()
df[cols].astype(int)8、知识点8匹配内容替换
#规范年份列数据 year = [] for y in df['年份']: a = re.search("[0-9][0-9][0-9][0-9]", y, re.X).group() year.append(a) df.loc[:, '年份'] = year
完整代码如下:
import pandas as pd import re df = pd.read_excel("./data/Olympic2.xlsx") #将国家列字符串中的空格都去除 df['国家'].replace('\s+','',regex=True,inplace=True) #删除金牌、银牌、铜牌都为空的行 cols=['金牌','银牌','铜牌'] df=df.loc[df[df[cols]!=""].dropna(thresh=1).index] #删除原中文标题(名次列为"名次"的行删除) df = df[-df["名次"].isin(["名次"])] ##删除奖牌数为国家的数据 #筛选列中不为数字的行 a = df[['名次']].apply(pd.to_numeric, errors='coerce').notnull().all(axis=1) #筛选列中不为数字的行对应的标题名称 title_list = df.loc[a==False,"标题"].drop_duplicates() df = df[-df["标题"].isin(title_list)] #规范年份列数据 year = [] for y in df['年份']: a = re.search("[0-9][0-9][0-9][0-9]", y, re.X).group() year.append(a) df.loc[:, '年份'] = year df.replace({'-':'0','–':'0','_':'0'},inplace=True) df.fillna('0', inplace=True) df[cols].astype(int) df.to_excel("./data/Olympic10.xlsx")
输出结果:
结 语
通过我们的一系列神操作,看到处理完成的数据,是不是感觉焕然一新。OF在本篇文章中对数据处理又补充了几个知识点,相信我们都对数据处理有了更深的理解。今天就写到这里,希望初学者们好好体会下思路,将复杂的事项拆分成一个个步骤,这样一点点的积累起来就能把项目做成功。在写python程序前,先构思下步骤,再根据步骤一个个完成。本系列还剩下最后一篇文章动态排序正向您招手,尽请期待。
1、数据采集-爬虫;
Bertram Xu:-历届奥运会奖牌动态排序动画(Python数据采集)2、数据处理-数据清洗;(本篇文章)
3、数据动态排序。