东京奥运会已经过去一大半,也将在8月8日迎来闭幕式。
截止至完稿日,中国已经获得69枚奖牌,其中金牌数量32枚,已经超过2016年里约奥运会的金牌数了!
今年的中国代表团也再一次创造了很多奇迹。
男子田径100米项目中,苏炳添在半决赛中以9.83秒的成绩刷新了亚洲纪录。
 图源网络
女子田径800米项目中,王春雨以1分59秒14排名小组第二,成功晋级决赛,成为中国晋级800米奥运会决赛的第一人!

图源网络
中国举重队也以七金一银的好成绩完美收官,创造中国举重的奥运会最佳战绩。

图源网络
男子50米步枪三姿决赛中,21岁的中国选手张常鸿以总成绩466夺金,并创造新的世界纪录。

图源网络
中国跳水队也实现了女子单人3米板项目的九连冠。
其中深受大家喜爱的乒乓球男单,女单项目中,中国运动员也再一次包揽了金牌银牌。
这也让人想起了08年北京奥运会乒乓球男单女单6面红旗升起的盛况!

图源网络
说起08年奥运会的这场盛况,那必然要提到乒乓球男单冠军马琳的一个乌龙小趣事。

今年6月,有网友在专业编程网站上看到了一个熟悉的名字——马琳。不仅头像是马琳本人,而且个人简介一栏中,还写明了“奥运乒乓球男单冠军”。

图源网络
有网友调侃称,不仅代码写不过别人,乒乓球也打不过。

但事实上,现在马琳不仅担任国乒女队教练组长,混双组长,同时还是奥运队员陈梦、刘诗雯的主管教练。
这位编程大师“马琳”大概只是一位忠实的铁杆粉丝罢了。

自己也深受启发,参照着这篇博文也使用pyecharts进行了一些数据可视化操作 。

这次我们使用的 pyecharts 也在之前的干货中介绍过,有兴趣的同学可以点下方链接看一看。 
饼状图分析
(温馨小提示:数据不包含本届奥运会数据) 首先,我们可以通过代码看看夏季奥运会各项运动产生的金牌占比: background_color_js = """new echarts.graphic.RadialGradient(0.5, 0.5, 1, [{ offset: 0, color: '#696969' }, { offset: 1, color: '#000000' }])"""tab = Tab()temp = data[(data['Medal']=='Gold') & (data['Season']=='Summer')]event_medal = temp.groupby(['Sport'])['Event'].nunique().reset_index()event_medal.columns = ['Sport', 'Nums']event_medal = event_medal.sort_values(by="Nums" , ascending=False)pie = (Pie(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width='1000px', height='800px')) .add('金牌️', [(row['Sport'], row['Nums']) for _, row in event_medal.iterrows()], radius=["30%", "75%"], rosetype="radius") .set_global_opts(title_opts=opts.TitleOpts(title="夏季奥运会各项运动产生金牌占比", pos_left="center", title_textstyle_opts=opts.TextStyleOpts(color="white", font_size=20), ), legend_opts=opts.LegendOpts(is_show=False)) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"), tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"),) )tab.add(pie, '夏奥会')tab.render(path='olympic_1.html')

也可以设置pandas筛选条件筛选出中国在夏季奥运会获得奖牌的分布: background_color_js = """new echarts.graphic.RadialGradient(0.5, 0.5, 1, [{ offset: 0, color: '#696969' }, { offset: 1, color: '#000000' }])"""tab = Tab()temp = data[(data['Medal']=='Gold') & (data['NOC']=='CHN') & (data['Season']=='Summer')]event_medal = temp.groupby(['Sport'])['Event'].nunique().reset_index()event_medal.columns = ['Sport', 'Nums']event_medal = event_medal.sort_values(by="Nums" , ascending=False)pie = (Pie(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width='1000px', height='800px')) .add('金牌️', [(row['Sport'], row['Nums']) for _, row in event_medal.iterrows()], radius=["30%", "75%"], rosetype="radius") .set_global_opts(title_opts=opts.TitleOpts(title="夏季奥运会各项运动产生金牌占比", pos_left="center", title_textstyle_opts=opts.TextStyleOpts(color="white", font_size=20), ), legend_opts=opts.LegendOpts(is_show=False)) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"), tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"),) )tab.add(pie, '夏奥会')tab.render(path='olympic_2.html')

关注乒乓球赛事的同学们可以通过pandas筛选条件筛选出乒乓球赛事,再按照国家分类, background_color_js = """new echarts.graphic.RadialGradient(0.5, 0.5, 1, [{ offset: 0, color: '#696969' }, { offset: 1, color: '#000000' }])"""tab = Tab()temp = data[(data['Medal']=='Gold') & (data['Sport']=='Table Tennis') & (data['Season']=='Summer')]event_medal = temp.groupby(['NOC'])['Event'].nunique().reset_index()event_medal.columns = ['NOC', 'Nums']event_medal = event_medal.sort_values(by="Nums" , ascending=False)pie = (Pie(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width='1000px', height='800px')) .add('金牌️', [(row['NOC'], row['Nums']) for _, row in event_medal.iterrows()], radius=["30%", "75%"], rosetype="radius") .set_global_opts(title_opts=opts.TitleOpts(title="夏季奥运会乒乓球产生金牌占比", pos_left="center", title_textstyle_opts=opts.TextStyleOpts(color="white", font_size=20), ), legend_opts=opts.LegendOpts(is_show=False)) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"), tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"),) )tab.add(pie, '夏奥会')tab.render(path='olympic_3.html')

可以发现我国乒乓球赛事占据了几乎所有金牌,主要的竞争对手为韩国和瑞士。 回到中国代表队这边,我们筛选下看看中国代表队中按照运动员分布的金牌情况: background_color_js = """new echarts.graphic.RadialGradient(0.5, 0.5, 1, [{ offset: 0, color: '#696969' }, { offset: 1, color: '#000000' }])"""tab = Tab()temp = data[(data['Medal']=='Gold') & (data['NOC']=='CHN') & (data['Sport']=='Table Tennis') & (data['Season']=='Summer')]event_medal = temp.groupby(['Name'])['Event'].nunique().reset_index()event_medal.columns = ['Name', 'Nums']event_medal = event_medal.sort_values(by="Nums" , ascending=False)pie = (Pie(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width='1000px', height='800px')) .add('金牌️', [(row['Name'], row['Nums']) for _, row in event_medal.iterrows()], radius=["30%", "75%"], rosetype="radius") .set_global_opts(title_opts=opts.TitleOpts(title="夏季奥运会乒乓球产生金牌占比", pos_left="center", title_textstyle_opts=opts.TextStyleOpts(color="white", font_size=20), ), legend_opts=opts.LegendOpts(is_show=False)) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"), tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b}: {c} ({d}%)"),) )tab.add(pie, '夏奥会')tab.render(path='olympic_4.html')

发现,马琳,王楠,张怡宁获取了最多的金牌,可想而知在中国乒乓球代表队中,马琳,王楠,张怡宁的时代,中国乒乓球有多么的辉煌。
插播一个小知识点01
前面都是使用饼图进行绘制图表,可能大家对pyecharts的内容有些不了解,我们在下方做一些简要介绍:

对于我们的饼图定义,我们使用 pyecharts.charts.Pie 类,其中我们需要传入 init_opts, 作为我们的设置内容,
有关 opts设置的内容如下:

可以通过这些参数对图标的大小,像素,标题,主题,以及图像背景进行设置。
设置好这些之后,我们可以添加饼图:func pyecharts.charts.Pie.add def add( # 系列名称,用于 tooltip 的显示,legend 的图例筛选。 series_name: str, # 系列数据项,格式为 [(key1, value1), (key2, value2)] data_pair: types.Sequence[types.Union[types.Sequence, opts.PieItem, dict]], # 系列 label 颜色 color: Optional[str] = None, # 饼图的半径,数组的第一项是内半径,第二项是外半径 # 默认设置成百分比,相对于容器高宽中较小的一项的一半 radius: Optional[Sequence] = None, # 饼图的中心(圆心)坐标,数组的第一项是横坐标,第二项是纵坐标 # 默认设置成百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高度 center: Optional[Sequence] = None, # 是否展示成南丁格尔图,通过半径区分数据大小,有'radius'和'area'两种模式。 # radius:扇区圆心角展现数据的百分比,半径展现数据的大小 # area:所有扇区圆心角相同,仅通过半径展现数据大小 rosetype: Optional[str] = None, # 饼图的扇区是否是顺时针排布。 is_clockwise: bool = True, # 标签配置项,参考 `series_options.LabelOpts` label_opts: Union[opts.LabelOpts, dict] = opts.LabelOpts(), # 提示框组件配置项,参考 `series_options.TooltipOpts` tooltip_opts: Union[opts.TooltipOpts, dict, None] = None, # 图元样式配置项,参考 `series_options.ItemStyleOpts` itemstyle_opts: Union[opts.ItemStyleOpts, dict, None] = None, # 可以定义 data 的哪个维度被编码成什么。 encode: types.Union[types.JSFunc, dict, None] = None,)
类似其他数据可视化库,有着同样的一些设置,比如color去设置颜色序列,radius设置饼图半径,label_opts设置标签等等。
给出一个具体例子如下:

Pie定义一个饼图类,add添加数据,我们用一个list去存储我们的数据进行添加,后续的都是设置操作,render为展示操作,以浏览器文件的方式进行展示。

折线图分析
除了饼图之外,我们一般还会使用折线图进行操作,我们将中国乒乓球代表队的历年得奖情况进行一个分析展示:
background_color_js = ( "new echarts.graphic.LinearGradient(1, 1, 0, 0, " "[{offset: 0, color: '#008B8B'}, {offset: 1, color: '#FF6347'}], false)")tab = Tab()temp = data[(data['NOC']=='CHN') & (data['Sport']=='Table Tennis') & (data['Season']=='Summer')]event_medal = temp.groupby(['Year'])['Event'].nunique().reset_index()event_medal.columns = ['Year', 'Nums']event_medal = event_medal.sort_values(by="Year" , ascending=False)line = ( Line(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width='1000px', height='600px')) .add_xaxis(event_medal['Year']) .add_yaxis("夏季奥运会", event_medal['Nums'], is_smooth=True, is_connect_nones=True, symbol="circle", symbol_size=6, linestyle_opts=opts.LineStyleOpts(color="#fff"), label_opts=opts.LabelOpts(is_show=False, position="top", color="white"), itemstyle_opts=opts.ItemStyleOpts( color="green", border_color="#fff", border_width=3), tooltip_opts=opts.TooltipOpts(is_show=True)) .set_global_opts(title_opts=opts.TitleOpts(title="中国乒乓球代表队得奖趋势", pos_left="center", title_textstyle_opts=opts.TextStyleOpts(color="white", font_size=20),), legend_opts=opts.LegendOpts(is_show=True, pos_top='5%', textstyle_opts=opts.TextStyleOpts(color="white", font_size=12)), xaxis_opts=opts.AxisOpts(type_="value", min_=1980, max_=2016, boundary_gap=False, axislabel_opts=opts.LabelOpts(margin=30, color="#ffffff63", formatter=JsCode("""function (value) {return value+'年';}""")), axisline_opts=opts.AxisLineOpts(is_show=False), axistick_opts=opts.AxisTickOpts( is_show=True, length=25, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"), ), splitline_opts=opts.SplitLineOpts( is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f") ), ), yaxis_opts=opts.AxisOpts( type_="value", position="right", axislabel_opts=opts.LabelOpts(margin=20, color="#ffffff63"), axisline_opts=opts.AxisLineOpts( linestyle_opts=opts.LineStyleOpts(width=2, color="#fff") ), axistick_opts=opts.AxisTickOpts( is_show=True, length=15, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"), ), splitline_opts=opts.SplitLineOpts( is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f") ), ),))line.render(path='olympic_5.html')

可以发现除了刚开始参加的时候只获得了3项冠军,接下来几乎每届运动会都包揽所有冠军了。
这里我们再加入其他国家的的数据进行一个比较。
background_color_js = ( "new echarts.graphic.LinearGradient(1, 1, 0, 0, " "[{offset: 0, color: '#008B8B'}, {offset: 1, color: '#FF6347'}], false)")tab = Tab()temp = data[(data['NOC']=='CHN') & (data['Sport']=='Table Tennis') & (data['Season']=='Summer')]event_medal = temp.groupby(['Year'])['Event'].nunique().reset_index()event_medal.columns = ['Year', 'Nums']event_medal = event_medal.sort_values(by="Year" , ascending=False)temp2 = data[(data['NOC']=='KOR') & (data['Sport']=='Table Tennis') & (data['Season']=='Summer')]event_medal2 = temp2.groupby(['Year'])['Event'].nunique().reset_index()event_medal2.columns = ['Year', 'Nums']event_medal2 = event_medal2.sort_values(by="Year" , ascending=False)temp3 = data[(data['NOC']=='SWE') & (data['Sport']=='Table Tennis') & (data['Season']=='Summer')]event_medal3 = temp3.groupby(['Year'])['Event'].nunique().reset_index()event_medal3.columns = ['Year', 'Nums']event_medal3 = event_medal3.sort_values(by="Year" , ascending=False)line = ( Line(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js), width='1000px', height='600px')) .add_xaxis(event_medal['Year']) .add_yaxis("中国代表队", event_medal['Nums'], is_smooth=True, is_connect_nones=True, symbol="circle", symbol_size=6, linestyle_opts=opts.LineStyleOpts(color="#fff"), label_opts=opts.LabelOpts(is_show=False, position="top", color="white"), itemstyle_opts=opts.ItemStyleOpts( color="green", border_color="#fff", border_width=3), tooltip_opts=opts.TooltipOpts(is_show=True)) .add_yaxis("韩国代表队", event_medal2['Nums'], is_smooth=True, is_connect_nones=True, symbol="circle", symbol_size=6, linestyle_opts=opts.LineStyleOpts(color="#FF4500"), label_opts=opts.LabelOpts(is_show=False, position="top", color="white"), itemstyle_opts=opts.ItemStyleOpts( color="red", border_color="#fff", border_width=3), tooltip_opts=opts.TooltipOpts(is_show=True)) .add_yaxis("瑞典代表队", event_medal3['Nums'], is_smooth=True, is_connect_nones=True, symbol="circle", symbol_size=6, linestyle_opts=opts.LineStyleOpts(color="#000000"), label_opts=opts.LabelOpts(is_show=False, position="top", color="white"), itemstyle_opts=opts.ItemStyleOpts( color="black", border_color="#fff", border_width=3), tooltip_opts=opts.TooltipOpts(is_show=True)) .set_global_opts(title_opts=opts.TitleOpts(title="中国乒乓球代表队得奖趋势", pos_left="center", title_textstyle_opts=opts.TextStyleOpts(color="white", font_size=20),), legend_opts=opts.LegendOpts(is_show=True, pos_top='5%', textstyle_opts=opts.TextStyleOpts(color="white", font_size=12)), xaxis_opts=opts.AxisOpts(type_="value", min_=1980, max_=2016, boundary_gap=False, axislabel_opts=opts.LabelOpts(margin=30, color="#ffffff63", formatter=JsCode("""function (value) {return value+'年';}""")), axisline_opts=opts.AxisLineOpts(is_show=False), axistick_opts=opts.AxisTickOpts( is_show=True, length=25, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"), ), splitline_opts=opts.SplitLineOpts( is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f") ), ), yaxis_opts=opts.AxisOpts( type_="value", position="right", axislabel_opts=opts.LabelOpts(margin=20, color="#ffffff63"), axisline_opts=opts.AxisLineOpts( linestyle_opts=opts.LineStyleOpts(width=2, color="#fff") ), axistick_opts=opts.AxisTickOpts( is_show=True, length=15, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"), ), splitline_opts=opts.SplitLineOpts( is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f") ), ),))line.render(path='olympic_6.html')
可以看到我们的对手韩国队一直在乒乓球项目上发挥着自己的潜力。
包括从08年北京奥运会开始瑞典代表队也有一名非常出色的运动员冲击着乒乓球项目的冠军,这点也是不容小觑的。

插播一个小知识点02 
这里我们也对pyecharts的折线图做简要的介绍:

和饼图类似,我们通过func pyecharts.charts.Line.add_yaxis 进行添加我们的x坐标或者y坐标
def add_yaxis( # 系列名称,用于 tooltip 的显示,legend 的图例筛选。 series_name: str, # 系列数据 y_axis: types.Sequence[types.Union[opts.LineItem, dict]], # 是否选中图例 is_selected: bool = True, # 是否连接空数据,空数据使用 `None` 填充 is_connect_nones: bool = False, # 使用的 x 轴的 index,在单个图表实例中存在多个 x 轴的时候有用。 xaxis_index: Optional[Numeric] = None, # 使用的 y 轴的 index,在单个图表实例中存在多个 y 轴的时候有用。 yaxis_index: Optional[Numeric] = None, # 系列 label 颜色 color: Optional[str] = None, # 是否显示 symbol, 如果 false 则只有在 tooltip hover 的时候显示。 is_symbol_show: bool = True, # 标记的图形。 # ECharts 提供的标记类型包括 'circle', 'rect', 'roundRect', 'triangle', # 'diamond', 'pin', 'arrow', 'none' # 可以通过 'image://url' 设置为图片,其中 URL 为图片的链接,或者 dataURI。 symbol: Optional[str] = None, # 标记的大小,可以设置成诸如 10 这样单一的数字,也可以用数组分开表示宽和高, # 例如 [20, 10] 表示标记宽为 20,高为 10。 symbol_size: Union[Numeric, Sequence] = 4, # 数据堆叠,同个类目轴上系列配置相同的 stack 值可以堆叠放置。 stack: Optional[str] = None, # 是否平滑曲线 is_smooth: bool = False, # 是否裁剪超出坐标系部分的图形。折线图:裁掉所有超出坐标系的折线部分,拐点图形的逻辑按照散点图处理 is_clip: bool = True, # 是否显示成阶梯图 is_step: bool = False, # 是否开启 hover 在拐点标志上的提示动画效果。 is_hover_animation: bool = True, # 折线图所有图形的 zlevel 值。 # zlevel用于 Canvas 分层,不同zlevel值的图形会放置在不同的 Canvas 中,Canvas 分层是一种常见的优化手段。 # zlevel 大的 Canvas 会放在 zlevel 小的 Canvas 的上面。 z_level: types.Numeric = 0, # 折线图组件的所有图形的z值。控制图形的前后顺序。z值小的图形会被z值大的图形覆盖。 # z 相比 zlevel 优先级更低,而且不会创建新的 Canvas。 z: types.Numeric = 0, # 标记点配置项,参考 `series_options.MarkPointOpts` markpoint_opts: Union[opts.MarkPointOpts, dict, None] = None, # 标记线配置项,参考 `series_options.MarkLineOpts` markline_opts: Union[opts.MarkLineOpts, dict, None] = None, # 提示框组件配置项,参考 `series_options.TooltipOpts` tooltip_opts: Union[opts.TooltipOpts, dict, None] = None, # 标签配置项,参考 `series_options.LabelOpts` label_opts: Union[opts.LabelOpts, dict] = opts.LabelOpts(), # 线样式配置项,参考 `series_options.LineStyleOpts` linestyle_opts: Union[opts.LineStyleOpts, dict] = opts.LineStyleOpts(), # 填充区域配置项,参考 `series_options.AreaStyleOpts` areastyle_opts: Union[opts.AreaStyleOpts, dict] = opts.AreaStyleOpts(), # 图元样式配置项,参考 `series_options.ItemStyleOpts` itemstyle_opts: Union[opts.ItemStyleOpts, dict, None] = None,)
举个最简单的例子:

add_xaxis,添加我们的x轴数据,如同其他可视化库一样,我们都用列表的方式传入我们的数据。
add_yaxis, 传入我们对应的y轴数据,也是使用列表的方式。
除此之外,散点图也是经常使用的可视化图表:

同样使用 func pyecharts.charts.Scatter.add_yaxis 我们可以进行添加散点图数据
def add_yaxis( # 系列名称,用于 tooltip 的显示,legend 的图例筛选。 series_name: str, # 系列数据 y_axis: Sequence, # 是否选中图例 is_selected: bool = True, # 使用的 x 轴的 index,在单个图表实例中存在多个 x 轴的时候有用。 xaxis_index: Optional[Numeric] = None, # 使用的 y 轴的 index,在单个图表实例中存在多个 y 轴的时候有用。 yaxis_index: Optional[Numeric] = None, # 系列 label 颜色 color: Optional[str] = None, # 标记的图形。 # ECharts 提供的标记类型包括 'circle', 'rect', 'roundRect', 'triangle', # 'diamond', 'pin', 'arrow', 'none' # 可以通过 'image://url' 设置为图片,其中 URL 为图片的链接,或者 dataURI。 symbol: Optional[str] = None, # 标记的大小,可以设置成诸如 10 这样单一的数字,也可以用数组分开表示宽和高, # 例如 [20, 10] 表示标记宽为 20,高为 10。 symbol_size: Numeric = 10, # 标记的旋转角度。注意在 markLine 中当 symbol 为 'arrow' 时会忽略 symbolRotate 强制设置为切线的角度。 symbol_rotate: types.Optional[types.Numeric] = None, # 标签配置项,参考 `series_options.LabelOpts` label_opts: Union[opts.LabelOpts, dict] = opts.LabelOpts(position="right"), # 标记点配置项,参考 `series_options.MarkPointOpts` markpoint_opts: Union[opts.MarkPointOpts, dict, None] = None, # 标记线配置项,参考 `series_options.MarkLineOpts` markline_opts: Union[opts.MarkLineOpts, dict, None] = None, # 图表标域,常用于标记图表中某个范围的数据,参考 `series_options.MarkAreaOpts` markarea_opts: types.MarkArea = None, # 提示框组件配置项,参考 `series_options.TooltipOpts` tooltip_opts: Union[opts.TooltipOpts, dict, None] = None, # 图元样式配置项,参考 `series_options.ItemStyleOpts` itemstyle_opts: Union[opts.ItemStyleOpts, dict, None] = None, # 可以定义 data 的哪个维度被编码成什么。 encode: types.Union[types.JSFunc, dict, None] = None,)
具体的例子如下: 


总结
通过代码以及数据,我们可以挖掘出数据更多的内容和信息,也可以通过代码进行更多的分析和更多元的可视化操作。
另外,乒乓球女子,男子团体比赛决赛将在8月5日和8月6日开赛,黄帮主已经做好定时装置,坐等比赛啦!
|