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
|