体育

此笔记本展示了如何使用 scikit-network 分析体育数据。

我们在这里考虑 ATP巡回赛 2001-2016 年期间的网球比赛结果。

[1]:
from IPython.display import SVG
[2]:
import numpy as np
import pandas as pd
from scipy import sparse
[3]:
from sknetwork.data import from_edge_list
from sknetwork.ranking import PageRank, top_k
from sknetwork.topology import get_core_decomposition
from sknetwork.utils import directed2undirected
from sknetwork.embedding import Spectral
from sknetwork.visualization import visualize_graph

加载数据

[4]:
filename = 'atp.csv'
[5]:
df = pd.read_csv(filename, sep=';')
[6]:
df.head()
[6]:
ATP 地点 锦标赛 日期 系列 球场 表面 轮次 最佳局数 获胜者 ... L4 W5 L5 Wsets Lsets 评论 MaxW MaxL AvgW AvgL
0 25 休斯顿 美国男子红土锦标赛 2005-04-21 国际 室外 红土 第二轮 3 哈斯 T. ... NaN NaN NaN 2.0 0.0 已完成 NaN NaN NaN NaN
1 26 埃斯托里尔 埃斯托里尔公开赛 2005-04-27 国际系列 室外 红土 第二轮 3 加乌迪奥 G. ... NaN NaN NaN 2.0 0.0 已完成 NaN NaN NaN NaN
2 28 罗马 意大利电信罗马大师赛 2005-05-03 大师 室外 红土 第一轮 3 桑古内蒂 D. ... NaN NaN NaN 2.0 1.0 已完成 NaN NaN NaN NaN
3 28 罗马 意大利电信罗马大师赛 2005-05-04 大师 室外 红土 第二轮 3 阿尔马格罗 N. ... NaN NaN NaN 2.0 0.0 已完成 NaN NaN NaN NaN
4 29 汉堡 汉堡 TMS 2005-05-11 大师 室外 红土 第二轮 3 赫巴蒂 D. ... NaN NaN NaN 2.0 0.0 已完成 NaN NaN NaN NaN

5 行 × 32 列

[7]:
df = df[df['Comment']=='Completed']
[8]:
len(df)
[8]:
42261

构建图

[9]:
edge_list = list(df[['Winner', 'Loser']].itertuples(index=False, name=None))
[10]:
len(edge_list)
[10]:
42261
[11]:
graph = from_edge_list(edge_list, directed=True)
[12]:
adjacency = graph.adjacency
names = graph.names
[13]:
adjacency
[13]:
<1255x1255 sparse matrix of type '<class 'numpy.int64'>'
        with 28212 stored elements in Compressed Sparse Row format>
[14]:
len(names)
[14]:
1255

排名

[15]:
# top-10 players in number of wins
out_weights = adjacency.dot(np.ones(len(names)))
print(names[top_k(out_weights, 10)])
['Federer R.' 'Nadal R.' 'Djokovic N.' 'Ferrer D.' 'Murray A.'
 'Roddick A.' 'Berdych T.' 'Robredo T.' 'Davydenko N.' 'Hewitt L.']
[16]:
# top-10 players in terms of PageRank
pagerank = PageRank()
adjacency_transpose = sparse.csr_matrix(adjacency.T)
scores = pagerank.fit_predict(adjacency_transpose)
print(names[top_k(scores, 10)])
['Federer R.' 'Nadal R.' 'Djokovic N.' 'Murray A.' 'Ferrer D.'
 'Roddick A.' 'Berdych T.' 'Hewitt L.' 'Davydenko N.' 'Wawrinka S.']
[17]:
index = top_k(scores, 10)
sub_adjacency = adjacency[index][:, index]
[18]:
SVG(visualize_graph(sub_adjacency, names=names[index], scores=scores[index]))
[18]:
../_images/use_cases_sport_22_0.svg

核心分解

[19]:
adjacency_sym = directed2undirected(adjacency)
[20]:
values = get_core_decomposition(adjacency_sym)
[21]:
print(names[values==np.max(values)])
['Acasuso J.' 'Almagro N.' 'Ancic M.' 'Anderson K.' 'Andreev I.'
 'Andujar P.' 'Baghdatis M.' 'Beck K.' 'Becker B.' 'Bellucci T.'
 'Benneteau J.' 'Berdych T.' 'Berlocq C.' 'Berrer M.' 'Bjorkman J.'
 'Blake J.' 'Bolelli S.' 'Calleri A.' 'Canas G.' 'Chardy J.' 'Chela J.I.'
 'Cilic M.' 'Clement A.' 'Coria G.' 'Cuevas P.' 'Darcis S.' 'Davydenko N.'
 'Del Potro J.M.' 'Dent T.' 'Dimitrov G.' 'Djokovic N.' 'Dodig I.'
 'Dolgopolov O.' 'Falla A.' 'Federer R.' 'Ferrer D.' 'Ferrero J.C.'
 'Fish M.' 'Fognini F.' 'Gabashvili T.' 'Garcia-Lopez G.' 'Gasquet R.'
 'Gaudio G.' 'Gicquel M.' 'Gimeno-Traver D.' 'Ginepri R.' 'Giraldo S.'
 'Golubev A.' 'Gonzalez F.' 'Granollers M.' 'Grosjean S.' 'Gulbis E.'
 'Haas T.' 'Haase R.' 'Hanescu V.' 'Harrison R.' 'Henman T.' 'Hernych J.'
 'Hewitt L.' 'Horna L.' 'Hrbaty D.' 'Isner J.' 'Istomin D.' 'Johansson T.'
 'Karlovic I.' 'Kiefer N.' 'Kohlschreiber P.' 'Korolev E.' 'Koubek S.'
 'Kubot L.' 'Kunitsyn I.' 'Lapentti N.' 'Lee H.T.' 'Ljubicic I.'
 'Llodra M.' 'Lopez F.' 'Lu Y.H.' 'Mahut N.' 'Malisse X.' 'Mannarino A.'
 'Martin A.' 'Massu N.' 'Mathieu P.H.' 'Mayer F.' 'Mayer L.' 'Melzer J.'
 'Mirnyi M.' 'Monaco J.' 'Monfils G.' 'Montanes A.' 'Moya C.' 'Muller G.'
 'Murray A.' 'Nadal R.' 'Nalbandian D.' 'Nieminen J.' 'Nishikori K.'
 'Novak J.' 'Paire B.' 'Pavel A.' 'Petzschner P.' 'Phau B.' 'Querrey S.'
 'Ramirez-Hidalgo R.' 'Raonic M.' 'Robredo T.' 'Rochus C.' 'Rochus O.'
 'Roddick A.' 'Roger-Vasselin E.' 'Rosol L.' 'Russell M.' 'Safin M.'
 'Santoro F.' 'Schuettler R.' 'Sela D.' 'Seppi A.' 'Serra F.' 'Simon G.'
 'Soderling R.' 'Spadea V.' 'Srichaphan P.' 'Stakhovsky S.' 'Starace P.'
 'Stepanek R.' 'Tipsarevic J.' 'Tomic B.' 'Troicki V.' 'Tsonga J.W.'
 'Tursunov D.' 'Verdasco F.' 'Vliegen K.' 'Volandri F.' 'Wawrinka S.'
 'Young D.' 'Youzhny M.' 'Zverev M.']

嵌入

[22]:
spectral = Spectral(2, normalized=False)
[23]:
embedding = spectral.fit_transform(adjacency)
[24]:
mask = values==np.max(values)
[25]:
SVG(visualize_graph(position=embedding[mask], names=names[mask], scores=scores[mask], node_size=5, width=400, height=1000))

[25]:
../_images/use_cases_sport_31_0.svg