1. 问题描述
第31届夏季奥林匹克运动会(Games of the XXXI Olympiad),又称2016年里约热内卢奥运会,共设28个大项,对应的可视化内容将在坐标系中显示所有的大项:其中,x轴表示大项奖牌的数量,y轴表示参与大项的运动员的数量。当使用交互式微件时,将能够筛选所显示的大项(在最大奖牌数量和最大运动员数量轴上)。每个大项采用不同的颜色显示,当悬停于其上时,将会显示每个项目相关的更多信息(如项目名称、运动员数量以及该大项中获得的金牌、银牌和铜牌的数量。
2.数据集描述
数据集包含里约奥运会参赛运动员的姓名、国籍、性别、参赛运动大项、所获奖牌等信息。
首先还是导入需要的一些包:
import pandas as pd
from ipywidgets import interact,widgets
import random
from bokeh.models import ColumnDataSource
from bokeh.plotting import show,figure
#from bokeh.io import output_notebook
#如果要在jupyter运行的话就要加上这一段
然后进行读入数据集:
#导入数据集
data = pd.read_csv('olympia2016_athletes.csv')
取出其中需要的东西,分别是28个体育项目,各个项目的运动员数量,各个项目的金牌数量:
sport = data['sport'].unique()#找到28个大项
y_number = data.groupby('sport').size()#各个项目运动员数量
j_number = data.groupby('sport')['gold','silver','bronze'].sum()#各个项目奖牌数量
这里可以写一个筛选,也就是两个微件来提供滑块进行筛选操作
max_j = j_number.sum(axis = 1).max()
max_y = y_number.max()
max_y_slider = widgets.IntSlider(value=max_y ,min = 0, max = max_y, step = 1 ,description = '运动员最大数量:',continuous_update = False,
orientation = 'vertical', layout ={'width':'100px'})
max_j_slider = widgets.IntSlider(value=max_j,min =0 ,max = max_j,step=1,description = '奖牌最大数量:' ,continuous_update = False,
orientation = 'horizontal')
然后写几个函数来完成画图,
首先是绘制颜色的函数,因为这里有28个项目,所以采取一个六进制十六位随机生成颜色:
def get_color():
return '%06x' % random.randint(0, 0xFFFFFF)
然后用bokeh带的ColumnDataSource处理数据并简化工具提示:
def get_dataset(filtered_sport):
return ColumnDataSource(data = dict(color = [get_color() for _ in filtered_sport],sport = filtered_sport,
gold = [j_number.loc[sports]['gold'] for sports in filtered_sport],
silver = [j_number.loc[sports]['silver'] for sports in filtered_sport],
bronze = [j_number.loc[sports]['bronze'] for sports in filtered_sport],
x=[j_number.loc[sports].sum() for sports in filtered_sport],
y = [y_number.loc[sports].sum() for sports in filtered_sport]))
然后进行最重要的绘制图表的设置,这里需要配置好需要绘制的内容和一些参数的设置:
def get_plot(max_y,max_j):
filtered_sport = []
for sports in sport:
if (y_number[sports] <= max_y and j_number.loc[sports].sum() <= max_j):
filtered_sport.append(sports)
dataset = get_dataset(filtered_sport)
TOOLTIPS = [('大项', '@sport'), ('运动员数量' , '@y'), ('金牌', '@gold'), ('银牌', '@silver'), ('铜牌' , '@bronze')]
plot = figure(title = '里约奥运会大项及奖牌数量', x_axis_label = '奖牌数量', y_axis_label = '运动员数量', plot_width = 800, plot_height = 500, tooltips = TOOLTIPS)
plot.circle('x','y', source = dataset,size = 20 ,color = 'color', alpha = 0.5)
return plot
然后就到了最后的展现自己的结果,写一个函数进行调用绘制图表的函数:
def get_stats(max_y,max_j):
show(get_plot(max_y, max_j))
这里展示自己的结果有两种方法,分为使用jupyter和pycharm运行,如果使用pycharm运行的话,只需要在代码的最后加一段代码:
get_stats(max_y,max_j)
pycharm运行的结果是:
而使用jupyter运行的话就更加的细致,会有两个滑块进行筛选,而使用jupyter运行的方式是,在写get_stats函数前加一个装饰器
@interact(max_y = max_y_slider,max_j = max_j_slider)
#调用绘制图表函数的函数
def get_stats(max_y,max_j):
show(get_plot(max_y, max_j))
这样就可以在jupyter上运行,还需要加上最开始的那一个包,
会有一个滑块筛选