数据隐私中nfl
无论您最近使用哪种媒体内容(播客,文章,推文等),都可能会遇到一些对数据的引用。 无论是备份谈话要点还是对数据无处不在进行元视图,对数据及其分析的需求都很高。
作为程序员,我发现数据科学比巫术更能比巫术更精确。 我渴望获得原始数据并从中收集有用和具体的东西的能力。 多么有用的人才!
这让我开始思考数据科学家和程序员之间的区别。 数据科学家不只是可以编码的统计学家吗? 环顾四周,您会看到许多旨在帮助开发人员成为数据科学家的工具。 AWS拥有一整套的机器学习课程 ,专门针对将开发人员转变为专家。 Visual Studio具有内置的Python项目,只需单击一个按钮,即可创建用于分类问题的完整模板。 数十名程序员正在编写旨在使任何人都容易上手的数据科学的工具。
我以为我会清楚地吸引到数据(或黑暗)方面来招聘程序员,并通过一个有趣的项目给它一个机会:训练一个机器学习模型,以使用国家橄榄球联盟(NFL)数据集预测比赛情况。
搭建环境
虚拟环境 。 这很重要,因为如果没有环境,我将无处工作。 幸运的是,Opensource.com拥有一些很棒的资源来安装和配置安装程序。您在这里看到的任何代码,我都可以查阅现有文档。 如果程序员熟悉一件事,那就是在浏览国外(有时非常稀疏)的文档。
获取数据
与任何现代问题一样,第一步是确保您拥有质量数据。 幸运的是,我遇到了2017年用于NFL大数据碗的一组NFL跟踪数据 。 甚至NFL也在尽力吸引数据领域中最耀眼的星星。
我需要了解的所有架构都在README中。 该练习将训练一个机器学习模型,以使用plays.csv 数据文件预测跑步(持球人保持足球状态并向低处奔跑)和传球(将球传给接收球员)。 在本练习中,我不会使用玩家跟踪数据,但是以后进行探索可能会很有趣。
首先,我需要通过将数据导入数据框来访问我的数据。 Pandas库是一个开放源代码的Python库,它提供用于轻松分析数据结构的算法。 样本NFL数据中的结构碰巧是一个二维数组(或更简单的说就是一个表),数据科学家通常将其称为数据框。 处理数据框的Pandas函数是pandas.DataFrame 。 我还将导入其他一些库,供以后使用。
import pandas
as pd
import numpy
as np
import seaborn
as sns
import matplotlib.
pyplot
as plt
import xgboost
as xgb
from sklearn
import metrics
df
= pd.
read_csv
(
'data/plays.csv'
)
print
(
len
( df
)
)
print
( df.
head
(
)
)
格式化数据
NFL数据转储未明确指示哪些播放是奔跑(也称为急速)和哪些是传球。 因此,我必须通过一些精明的足球和推理来对进攻性比赛类型进行分类。
现在,我可以在isSTPLAY列中摆脱特殊团队的比赛。 特种球队既不是进攻也不是防守,因此与我的目标无关。
#drop st plays
df
= df
[
~ df
[
'isSTPlay'
]
]
print
(
len
( df
)
)
略过playDescription列,我看到四分卫跪下的一些比赛,这实际上结束了一场比赛。 这通常被称为“胜利阵型”,因为这样做的目的是耗尽时间。 这些与正常的跑步比赛有很大的不同,所以我也可以放下它们。
#drop kneels
df
= df
[
~ df
[
'playDescription'
] .
str .
contains
(
"kneels"
)
]
print
(
len
( df
)
)
数据以正常进行游戏的季度为单位报告时间(以及每个季度的游戏时钟时间)。 就尝试预测序列而言,这是否最直观? 解决这个问题的一种方法是考虑时间间隔之间游戏玩法的差异。
当一支球队在第一节还剩一分钟的球时,是否会像在第二节还剩一分钟的球一样? 可能不是。 在两半结束时,只要花一分钟,它的作用是否相同? 所有其他条件保持不变,在大多数情况下答案可能是肯定的。
我将四分之一和GameClock列从四分之一转换为一半,以秒而不是分钟表示。 我还将根据四分之一数值创建一个半列。 有一些第五季度值,我认为这是加班费。 由于加班规则与正常游戏规则不同,因此我可以删除它们。
#drop overtime
df
= df
[
~
( df
[
'quarter'
]
==
5
)
]
print
(
len
( df
)
)
#convert time/quarters
def translate_game_clock
( row
) :
raw_game_clock
= row
[
'GameClock'
]
quarter
= row
[
'quarter'
]
minutes
, seconds_raw
= raw_game_clock.
partition
(
':'
)
[ ::
2
]
seconds
= seconds_raw.
partition
(
':'
)
[
0
]
total_seconds_left_in_quarter
=
int
( seconds
) +
(
int
( minutes
) *
60
)
if quarter
==
3
or quarter
==
1 :
return total_seconds_left_in_quarter +
900
elif quarter
==
4
or quarter
==
2 :
return total_seconds_left_in_quarter
if
'GameClock'
in
list
( df.
columns
) :
df
[
'secondsLeftInHalf'
]
= df.
apply
( translate_game_clock
, axis
=
1
)
if
'quarter'
in
list
( df.
columns
) :
df
[
'half'
]
= df
[
'quarter'
] .
map
(
lambda q:
2
if q
>
2
else
1
)
yardlineNumber列也需要转换。 当前数据将码列列出为从1到50的值。同样,这也无济于事,因为团队不会在自己的20码列和其对手的20码列上采取相同的行动。 我将其转换为代表从1到99的值,其中,一码线最接近控球区的终点区域,而99码线最接近对手的终点区。
def yards_to_endzone
( row
) :
if row
[
'possessionTeam'
]
== row
[
'yardlineSide'
] :
return
100 - row
[
'yardlineNumber'
]
else :
return row
[
'yardlineNumber'
]
df
[
'yardsToEndzone'
]
= df.
apply
( yards_to_endzone
, axis
=
1
)
如果我可以将人员数据转换成某种格式以供机器学习算法使用,则人员数据将非常有用。人员可以在给定的时间识别不同类型的技能职位。 目前在persons.offense中显示的字符串值不利于输入,因此我将把每个人员的位置转换为自己的列,以指示比赛中场上出现的数字。 国防人员稍后可能会感兴趣,以查看它是否对预测有任何结果。 现在,我只会坚持进攻。
def transform_off_personnel
( row
) :
rb_count
=
0
te_count
=
0
wr_count
=
0
ol_count
=
0
dl_count
=
0
db_count
=
0
if
not pd.
isna
( row
[
'personnel.offense'
]
) :
personnel
= row
[
'personnel.offense'
] .
split
(
', '
)
for p
in personnel:
if p
[
2 :
4
]
==
'RB' :
rb_count
=
int
( p
[
0
]
)
elif p
[
2 :
4
]
==
'TE' :
te_count
=
int
( p
[
0
]
)
elif p
[
2 :
4
]
==
'WR' :
wr_count
=
int
( p
[
0
]
)
elif p
[
2 :
4
]
==
'OL' :
ol_count
=
int
( p
[
0
]
)
elif p
[
2 :
4
]
==
'DL' :
dl_count
=
int
( p
[
0
]
)
elif p
[
2 :
4
]
==
'DB' :
db_count
=
int
( p
[
0
]
)
return pd.
Series
(
[ rb_count
, te_count
, wr_count
, ol_count
, dl_count
, db_count
]
)
df
[
[
'rb_count'
,
'te_count'
,
'wr_count'
,
'ol_count'
,
'dl_count'
,
'db_count'
]
]
= df.
apply
( transform_off_personnel
, axis
=
1
)
现在,进攻人员值由单独的列表示。
![重新格式化犯罪人员的结果 Result of reformatting offense personnel](https://i-blog.csdnimg.cn/blog_migrate/2a0a88244ba0c5440ed94fe393f0a038.png)
编队描述了球员在球场上的位置,这在预测比赛结果方面似乎也具有价值。 再一次,我将字符串值转换为整数。
df
[
'offenseFormation'
]
= df
[
'offenseFormation'
] .
map
(
lambda f :
'EMPTY'
if pd.
isna
( f
)
else f
)
def formation
( row
) :
form
= row
[
'offenseFormation'
] .
strip
(
)
if form
==
'SHOTGUN' :
return
0
elif form
==
'SINGLEBACK' :
return
1
elif form
==
'EMPTY' :
return
2
elif form
==
'I_FORM' :
return
3
elif form
==
'PISTOL' :
return
4
elif form
==
'JUMBO' :
return
5
elif form
==
'WILDCAT' :
return
6
elif form
==
'ACE' :
return
7
else :
return -
1
df
[
'numericFormation'
]
= df.
apply
( formation
, axis
=
1
)
print
( df.
yardlineNumber .
unique
(
)
)
最后,是时候对播放类型进行分类了。 PassResult列具有四个不同的值:I,C,S和null,分别表示不完整的传球,完整的传球,麻袋(分类为传球)和空值。 由于我已经淘汰了所有特殊的团队比赛,因此我可以假设空值是连续比赛。 因此,我将播放结果转换为一个名为play_type的列,该列由0表示运行或1表示通过。 这将是我希望算法预测的列(或标签 ,如数据科学家所说)。
def play_type
( row
) :
if row
[
'PassResult'
]
==
'I'
or row
[
'PassResult'
]
==
'C'
or row
[
'PassResult'
]
==
'S' :
return
'Passing'
else :
return
'Rushing'
df
[
'play_type'
]
= df.
apply
( play_type
, axis
=
1
)
df
[
'numericPlayType'
]
= df
[
'play_type'
] .
map
(
lambda p:
1
if p
==
'Passing'
else
0
)
休息一下
现在该开始预测事情了吗? 到目前为止,我的大部分工作一直在试图理解数据及其需要采用的格式,甚至在我开始进行任何预测之前。 其他人需要一分钟吗?
在第二部分中,我将对数据进行一些分析和可视化,然后将其输入到机器学习算法中,然后对模型的结果进行评分,以查看它们的准确性。 敬请关注!
翻译自: https://opensource.com/article/19/10/formatting-nfl-data-python
数据隐私中nfl