剖析勇士如何成为新赛季夺冠热门:基于Spark GraphFrames的金州勇士传球网络分析
databricks 最近发布了 GraphFrames,这是一个用 DataFrames 封装图处理过程的Spark插件。我评估了网络分析并且利用丰富的NBA.com的数据对金州勇士的传球网络进行可视化。金州勇士的传球网络传接球联盟 MVP Stephen Curry 接到了大多数的传球,而团队中的 MVP Draymond Green则发动了最多的传球。

databricks 最近发布了 GraphFrames,这是一个用 DataFrames 封装图处理过程的Spark插件。
我评估了网络分析并且利用丰富的NBA.com的数据对金州勇士的传球网络进行可视化。

金州勇士的传球网络
传接球
联盟 MVP Stephen Curry 接到了大多数的传球,而团队中的 MVP Draymond Green则发动了最多的传球。
我们已经看到大多数的进攻是由 Curry 和 Green 的相互传球开始的。

图片来自 GIPHY
入度 inDegree
| id | inDegree |
|---|---|
| CurryStephen | 3993 |
| GreenDraymond | 3123 |
| ThompsonKlay | 2276 |
| LivingstonShaun | 1925 |
| IguodalaAndre | 1814 |
| BarnesHarrison | 1241 |
| BogutAndrew | 1062 |
| BarbosaLeandro | 946 |
| SpeightsMarreese | 826 |
| ClarkIan | 692 |
| RushBrandon | 685 |
| EzeliFestus | 559 |
| McAdooJames Michael | 182 |
| VarejaoAnderson | 67 |
| LooneyKevon | 22 |
出度 outDegree
| id | outDegree |
|---|---|
| GreenDraymond | 3841 |
| CurryStephen | 3300 |
| IguodalaAndre | 1896 |
| LivingstonShaun | 1878 |
| BogutAndrew | 1660 |
| ThompsonKlay | 1460 |
| BarnesHarrison | 1300 |
| SpeightsMarreese | 795 |
| RushBrandon | 772 |
| EzeliFestus | 765 |
| BarbosaLeandro | 758 |
| ClarkIan | 597 |
| McAdooJames Michael | 261 |
| VarejaoAnderson | 94 |
| LooneyKevon | 36 |
标签传递算法 (Label Propagation Algorithm)
标签传递是一种在图网络中寻找队伍的算法。
这种算法在没有已有标签的情况下,依然可以很好地将球员分为前锋和后卫。
| 名字 | 标签 |
|---|---|
| Thompson, Klay | 3 |
| Barbosa, Leandro | 3 |
| Curry, Stephen | 3 |
| Clark, Ian | 3 |
| Livingston, Shaun | 3 |
| Rush, Brandon | 7 |
| Green, Draymond | 7 |
| Speights, Marreese | 7 |
| Bogut, Andrew | 7 |
| McAdoo, James Michael | 7 |
| Iguodala, Andre | 7 |
| Varejao, Anderson | 7 |
| Ezeli, Festus | 7 |
| Looney, Kevon | 7 |
| Barnes, Harrison | 7 |
网页排名算法 (Pagerank Algorithm)
在一个网络中 PageRank 可以检测节点的重要程度。
毫无疑问,Stephen Curry、 Draymond Green 和 Klay Thompson 是Top3.
这个算法可以发现 Shaun Livingston 和 Andre Iguodala 在金州勇士的传球中扮演着关键角色。
| name | pagerank |
|---|---|
| Curry, Stephen | 2.17 |
| Green, Draymond | 1.99 |
| Thompson, Klay | 1.34 |
| Livingston, Shaun | 1.29 |
| Iguodala, Andre | 1.21 |
| Barnes, Harrison | 0.86 |
| Bogut, Andrew | 0.77 |
| Barbosa, Leandro | 0.72 |
| Speights, Marreese | 0.66 |
| Clark, Ian | 0.59 |
| Rush, Brandon | 0.57 |
| Ezeli, Festus | 0.48 |
| McAdoo, James Michael | 0.27 |
| Varejao, Anderson | 0.19 |
| Looney, Kevon | 0.16 |
示例
|
1
2
3
4
|
library ( networkD3 )
setwd ( '/Users/yuki/Documents/code_for_blog/gsw_passing_network' )
passes
|

- 节点大小: pagerank值
- 节点颜色: 队伍
- 连线宽度: 传球次数(接球和发球)
工作流
调用API
我使用 playerdashptpass 的端点并且将同队所有球员数据保存到本地的 JSON 文件中。
数据来自 2015-16赛季的传球记录。
|
1
2
3
4
5
6
7
8
|
# 金州勇士球员 IDs
playerids = [ 201575 , 201578 , 2738 , 202691 , 101106 , 2760 , 2571 , 203949 , 203546 ,
203110 , 201939 , 203105 , 2733 , 1626172 , 203084 ]
# 调用 API 并且存储结果为 JSON
for playerid in playerids :
os . system ( 'curl "http://stats.nba.com/stats/playerdashptpass?'
' DateFrom =
|
JSON -> Panda’s DataFrame
接着,我结合每个JSON文件到一个 DataFrame 中。
|
1
2
3
4
5
6
7
8
9
10
|
raw = pd . DataFrame ( )
for playerid in playerids :
with open ( "{playerid}.json" . format ( playerid = playerid ) ) as json_file :
parsed = json . load ( json_file ) [ 'resultSets' ] [ 0 ]
raw = raw . append (
pd . DataFrame ( parsed [ 'rowSet' ] , columns = parsed [ 'headers' ] ) )
raw = raw . rename ( columns = { 'PLAYER_NAME_LAST_FIRST' : 'PLAYER' } )
raw [ 'id' ] = raw [ 'PLAYER' ] . str . replace ( ', ' , '' )
|
准备节点和边
你需要为 Spark 中的 GraphFrames 准备一个像点+边的特殊的数据格式。顶点表示了图中的节点和运动员ID,边表示节点之间的关系。你可以添加一些附加特征比如权重,但是你没法找出在稍后的分析中可以更好表现的特征。一个可行的办法是尝试穷举所有的可能方案。(也欢迎大家留言讨论)
|
1
2
3
4
5
6
7
8
|
# 生成初始节点
pandas_vertices = raw [ [ 'PLAYER' , 'id' ] ] . drop_duplicates ( )
pandas_vertices . columns = [ 'name' , 'id' ]
# 生成初始边
pandas_edges = pd . DataFrame ( )
for passer in raw [ 'id' ] . drop_duplicates ( ) :
for receiver in raw [ ( raw [ 'PASS_TO' ] . isin ( raw [ 'PLAYER' ] ) )
|
图分析
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
vertices = sqlContext . createDataFrame ( pandas_vertices )
edges = sqlContext . createDataFrame ( pandas_edges )
# Analysis part
g = GraphFrame ( vertices , edges )
print ( "vertices" )
g . vertices . show ( )
print ( "edges" )
g . edges . show ( )
print ( "inDegrees" )
g . inDegrees . sort ( 'inDegree' , ascending = False ) . show ( )
print ( "outDegrees" )
g . outDegrees . sort ( 'outDegree' , ascending = False ) . show ( )
print ( "degrees" )
g . degrees . sort ( 'degree' , ascending = False ) . show ( )
print ( "labelPropagation" )
g . labelPropagation ( maxIter = 5 ) . show ( )
print ( "pageRank" )
g . pageRank ( resetProbability = 0.15 , tol = 0.01 ) . vertices . sort (
'pagerank' , ascending = False ) . show ( )
|
网络可视化
当你运行 GitHub 仓库中的代码 gsw_passing_network.py,你需要检查在工作目录下有 passes.csv、groups.csv、size.csv 这三个文件。我用R中的networkD3包来实现酷炫的可交互的 D3 制图。
|
1
2
3
4
|
library ( networkD3 )
setwd ( '/Users/yuki/Documents/code_for_blog/gsw_passing_network' )
passes
|
参考资料
更多推荐


所有评论(0)