引子
计算机最棒的一点在于,它们能够将表格数据转换成更直观的图形表示。常常令我费解的是,明明可以将数据转化为图形表达,但大部分人却往往放弃了这个可视化机会。
例如,在 ESPN 上有一篇关于不同裁判判罚方式之间的差异的论文。这篇论文的数据相当有趣, 包含了显示裁判判罚方式差异的数据。
然而,我发现了一件略为尴尬的事,作者企图将表格数据可视化,但最后并没有实现。这或许是因为作者不知道该如何对这些数据作出最好的可视化,来讲述他的数据故事。因此,我决定帮他达到这个目的!
给定一个前提,假设裁判的判罚方式之间的确存在差异。基于这个前提,我们想要弄明白,他们的判罚方式的差异究竟在哪里。
下面的数据是来自文章中的表格数据:
论文作者指出:
Jeff Triplette 团队迄今总共判决出了 81 次判罚,比判罚次数仅次于他们的团队高出 18 次,是另外两个团队的 2 倍多。
论文作者接下来便继续谈论了他与正在推销新书的 Mike Pereira 的会面。
虽然上面的表格很有用,但它并没有经过任何可视化操作,你看到了可能会问:“天哪,这到底说明了些什么?”。直觉上来说,表格中的数据在有些地方不太对劲…但是我又说不清楚是什么不对劲。
让我们加总一下各个裁判团队判罚的防守点球数(防守越位、侵犯和中立区犯规数),看看数据会变成什么样:
现在,我们可以看到这些数据可能向我们揭示了什么,但这对偏好图形的人来说,还是会有些理解上的困难。如果我们利用这些数据,生成散点图,那就达到利用图形来展示这个问题的目的了。我们可以通过以下代码,绘出散点图:
In[1]:
from bs4 import BeautifulSoup import pandas as pd import requests import matplotlib.pyplot as plt import scipy import numpy url = 'http://www.espn.com/blog/nflnation/post/_/id/225804/aaron-rodgers-could-get-some-help-from-referee-jeff-triplette' r = requests.get(url) tables = BeautifulSoup(r.text, 'lxml').find_all('table', class_='inline-table') CrewName = [] DefOffside = [] Encroach = [] FalseStart = [] NeutralZone = [] for table in tables: for row in table.find_all('tr'): columns = row.find_all('td') try: CrewName.append(columns[0].text) DefOffside.append(int(columns[1].text)) Encroach.append(int(columns[2].text)) FalseStart.append(int(columns[3].text)) NeutralZone.append(int(columns[4].text)) except Exception as e: pass print('| REFEREE | DEF. OFFSIDE | ENCROACH | FALSE START | NEUTRAL ZONE |') print('| --- | --- | --- | --- | --- |') for i in range(0, len(CrewName)): print('|'+CrewName[i]+ '|'+str(DefOffside[i])+ '|'+str(Encroach[i])+ '|'+str(FalseStart[i])+ '|'+str(NeutralZone[i])+ '|') dic = {'Crew': CrewName, 'DefOffside': DefOffside, 'Encroach': Encroach, 'FalseStart': FalseStart, 'NeutralZone': NeutralZone} Penalties = pd.DataFrame(dic) Offensive = Penalties[['FalseStart']] Deffensive = Penalties['DefOffside'] + Penalties['Encroach'] + Penalties['NeutralZone'] #for i in range(0, len(CrewName)): N = len(CrewName) x = Offensive y = Deffensive xMax = x.max()['FalseStart'] xMin = x.min()['FalseStart'] yMax = y.max() yMin = y.min() xMean = x.mean()['FalseStart'] yMean = y.mean() xstd = x.std()['FalseStart'] ystd = y.std() StdDevs = 2 plt.scatter(x,y) plt.xlabel('Offensive Penalties') plt.ylabel('Deffensive Penalties') plt.title('Referee Crew Penalty Calls') plt.axvline(x=xMean, ls="--") graph_expansion = 15 borders = [(xMean-StdDevs*xstd)-graph_expansion, (xMean+StdDevs*xstd)+graph_expansion, (yMean-StdDevs*ystd)-graph_expansion, (yMean+StdDevs*ystd)+graph_expansion] box = [(xMean-StdDevs*xstd), (xMean+StdDevs*xstd), (yMean-StdDevs*ystd), (yMean+StdDevs*ystd)] plt.axhspan(ymin=box[2], ymax=box[3], xmin=(box[0] - borders[0]) / (borders[1] - borders[0]), xmax=(box[1] - borders[0]) / (borders[1] - borders[0]), facecolor='0.5', alpha= 0.25) plt.axis(borders) plt.axhline(y=yMean, ls="--") for i in range(0, N): if x.ix[i]['FalseStart'] > xMean+StdDevs*xstd or y.ix[i] > yMean+StdDevs*ystd or x.ix[i]['FalseStart'] < xMean-StdDevs*xstd or y.ix[i] < yMean-StdDevs*ystd: plt.annotate(CrewName[i], (x.ix[i]['FalseStart'],y.ix[i])) plt.show()
| REFEREE | DEF. OFFSIDE | ENCROACH | FALSE START | NEUTRAL ZONE | | --- | --- | --- | --- | --- | |Triplette, Jeff|39|2|34|6| |Anderson, Walt|12|2|39|10| |Blakeman, Clete|13|2|41|7| |Hussey, John|10|3|42|3| |Cheffers, Cartlon|22|0|31|3| |Corrente, Tony|14|1|31|8| |Steratore, Gene|19|1|29|5| |Torbert, Ronald|9|4|31|7| |Allen, Brad|15|1|28|6| |McAulay, Terry|10|4|23|12| |Vinovich, Bill|8|7|29|5| |Morelli, Peter|12|3|24|9| |Boger, Jerome|11|3|27|6| |Wrolstad, Craig|9|1|31|5| |Hochuli, Ed|5|2|33|4| |Coleman, Walt|9|2|25|4| |Parry, John|7|5|20|6|
上图中的蓝色水平虚线表示裁判的平均防守罚球点球数,蓝色竖直虚线表示裁判的平均侵犯判罚次数。灰色盒子表示由侵犯判罚次数和防守罚球点球数的 (μ2σ,μ+2σμ2σ,μ+2σ) 范围形成的区域。
是不是发现了什么?是的,我也注意到了。Jeff Triplette 团队在图上距离盒子如此之远,简直好像是他们裁判了一场假比赛一样,不过也有可能是他们看了假的裁判规则。
我希望我真正能做到的是,按照比赛规则,依据相同的分析过程,能对任一场比赛给出相应的分析。我并不指望这些分析会对 Jeff Triplette 团队以后的判罚方式产生什么影响,但不管怎样,这些分析向我们展示出了一些值得研究的异常数据点。
另外,你们能上我的 Github:https://github.com/miloardot/python-files/blob/master/Referees找到这个项目的全部代码。
译者:胡帆
本文为专栏文章,来自:数据工匠,内容观点不代表本站立场,如若转载请联系专栏作者,本文链接:https://www.afenxi.com/47572.html 。