美文网首页大数据 爬虫Python AI SqlPython小哥哥
采用 Python 机器学习预测足球比赛结果!买谁赢就谁赢!

采用 Python 机器学习预测足球比赛结果!买谁赢就谁赢!

作者: 14e61d025165 | 来源:发表于2019-05-08 15:26 被阅读0次

    采用 Python 机器学习预测足球比赛结果

    足球是世界上最火爆的运动之一,世界杯期间也往往是球迷们最亢奋的时刻。比赛狂欢季除了炸出了熬夜看球的铁杆粉丝,也让足球竞猜也成了大家茶余饭后最热衷的话题。甚至连原来不怎么看足球的人,也是暗中努力恶补了很多足球相关知识,想通过赛事竞猜先赚一个小目标。今天我们将介绍如何用机器学习来预测足球比赛结果!

    本 Chat 采用 Python 编程语言,使用 人工智能建模平台 Mo 作为在线开发环境进行编程,通过获取 2000 年到 2018 年共 19 年英超的比赛数据,然后基于监督学习中逻辑回归模型、支持向量机模型和 XGBoost 模型,对英超比赛结果进行预测。

    Python学习交流群:1004391443,这里是python学习者聚集地,有大牛答疑,有资源共享!小编也准备了一份python学习资料,有想学习python编程的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。

    下面我们一起来看看预测英超比赛结果的机器学习步骤:

    主要流程步骤

    1. 获取数据和读取数据的信息
    2. 数据清洗和预处理
    3. 特征工程
    4. 建立机器学习模型并进行预测
    5. 总结与展望

    1. 获取数据和读取数据的信息

    首先我们进入 Mo 工作台 ,创建一个空白项目,点击 开始开发 进入内嵌 JupyterLab 的 Notebook 开发环境。

    <tt-image data-tteditor-tag="tteditorTag" contenteditable="false" class="syl1557300310009" data-render-status="finished" data-syl-blot="image" style="box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;"> image <input class="pgc-img-caption-ipt" placeholder="图片描述(最多50字)" value="" style="box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s;"></tt-image> <tt-image data-tteditor-tag="tteditorTag" contenteditable="false" class="syl1557300310015" data-render-status="finished" data-syl-blot="image" style="box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;"> image

    <input class="pgc-img-caption-ipt" placeholder="图片描述(最多50字)" value="" style="box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s;"></tt-image>

    接着我们需要在项目中上传 数据集 。

    英超每年举办一个赛季,在每年的 8 月到第二年的 5 月进行,共有 20 支球队,实行主客场双循环赛制,每个赛季共 38 轮比赛(其中 19 场主场比赛,19 场客场比赛),每轮比赛共计 10 场比赛,所以每个赛季,英超共有 380 场比赛。

    • 数据集地址
    • 数据集中特征说明文档

    如果您已经在 MO 平台新建项目,可以在平台直接导入数据集,流程如下:

    <tt-image data-tteditor-tag="tteditorTag" contenteditable="false" class="syl1557300310022" data-render-status="finished" data-syl-blot="image" style="box-sizing: border-box; cursor: text; color: rgb(34, 34, 34); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;"> image

    <input class="pgc-img-caption-ipt" placeholder="图片描述(最多50字)" value="" style="box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s;"></tt-image>

    1.1 读取 csv 数据接口解释

    • 采用 Pandas 读取、写入数据 API 汇总网址

    读取 csv 数据一般采用 pandas.read_csv():

    pandas.read_csv(filepath_or_buffer, sep =',' , delimiter = None)

    • filepath_or_buffer:文件路径
    • sep:指定分隔符,默认是逗号
    • delimiter:定界符,备选分隔符(如果指定改参数,则sep失效)
    • usecols: 指定读取的列名,列表形式

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 导入必须的包
    import warnings
    warnings.filterwarnings('ignore') # 防止警告文件的包
    import pandas as pd # 数据分析包
    import os
    import matplotlib.pyplot as plt # 可视化包
    import matplotlib
    %matplotlib inline
    import seaborn as sns # 可视化包
    from time import time
    from sklearn.preprocessing import scale # 标准化操作
    from sklearn.model_selection import train_test_split # 将数据集分成测试集和训练集
    from sklearn.metrics import f1_score # F1得分
    import xgboost as xgb # XGBoost模型
    from sklearn.svm import SVC ## 支持向量机分类模型
    from sklearn.linear_model import LogisticRegression # 逻辑回归模型
    from sklearn.model_selection import GridSearchCV # 超参数调参模块
    from sklearn.metrics import make_scorer # 模型评估
    import joblib # 模型的保存与加载模块
    </pre>

    下面开始我们的表演:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 获取地址中的所有文件
    loc = './/football//' # 存放数据的路径
    res_name = [] # 存放数据名的列表
    filecsv_list = [] # 获取数据名后存放的列表
    def file_name(file_name):
    # root:当前目录路径 dirs:当前目录下所有子目录 files:当前路径下所有非目录文件
    for root,dirs,files in os.walk(file_name):
    files.sort() # 排序,让列表里面的元素有顺序
    for i,file in enumerate(files):
    if os.path.splitext(file)[1] == '.csv':
    filecsv_list.append(file)
    res_name.append('raw_data_'+str(i+1))
    print(res_name)
    print(filecsv_list)
    file_name(loc)
    ['raw_data_1', 'raw_data_2', 'raw_data_3', 'raw_data_4', 'raw_data_5', 'raw_data_6', 'raw_data_7', 'raw_data_8', 'raw_data_9', 'raw_data_10', 'raw_data_11', 'raw_data_12', 'raw_data_13', 'raw_data_14', 'raw_data_15', 'raw_data_16', 'raw_data_17', 'raw_data_18', 'raw_data_19']
    ['2000-01.csv', '2001-02.csv', '2002-03.csv', '2003-04.csv', '2004-05.csv', '2005-06.csv', '2006-07.csv', '2007-08.csv', '2008-09.csv', '2009-10.csv', '2010-11.csv', '2011-12.csv', '2012-13.csv', '2013-14.csv', '2014-15.csv', '2015-16.csv', '2016-17.csv', '2017-18.csv', '2018-19.csv']
    </pre>

    1.2 时间列表

    获取每一年的数据后,将每一年的年份放入到 time_list 列表中:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">time_list = [filecsv_list[i][0:4] for i in range(len(filecsv_list))]
    time_list
    </pre>

    ['2000','2001','2002','2003','2004','2005','2006','2007','2008','2009','2010','2011','2012','2013','2014','2015','2016','2017','2018']

    1.3 用 Pandas.read_csv() 接口读取数据

    读取时将数据与 res_name 中的元素名一一对应。

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">for i in range(len(res_name)):
    res_name[i] = pd.read_csv(loc+filecsv_list[i],error_bad_lines=False)
    print('第%2s个文件是%s,数据大小为%s'%(i+1,filecsv_list[i],res_name[i].shape))
    第 1个文件是2000-01.csv,数据大小为(380, 45)
    第 2个文件是2001-02.csv,数据大小为(380, 48)
    第 3个文件是2002-03.csv,数据大小为(316, 48)
    第 4个文件是2003-04.csv,数据大小为(335, 57)
    第 5个文件是2004-05.csv,数据大小为(335, 57)
    第 6个文件是2005-06.csv,数据大小为(380, 68)
    第 7个文件是2006-07.csv,数据大小为(380, 68)
    第 8个文件是2007-08.csv,数据大小为(380, 71)
    第 9个文件是2008-09.csv,数据大小为(380, 71)
    第10个文件是2009-10.csv,数据大小为(380, 71)
    第11个文件是2010-11.csv,数据大小为(380, 71)
    第12个文件是2011-12.csv,数据大小为(380, 71)
    第13个文件是2012-13.csv,数据大小为(380, 74)
    第14个文件是2013-14.csv,数据大小为(380, 68)
    第15个文件是2014-15.csv,数据大小为(381, 68)
    第16个文件是2015-16.csv,数据大小为(380, 65)
    第17个文件是2016-17.csv,数据大小为(380, 65)
    第18个文件是2017-18.csv,数据大小为(380, 65)
    第19个文件是2018-19.csv,数据大小为(304, 62)
    </pre>

    1.4 删除特定文件的空值

    经过查看第 15 个文件读取的第 381 行为空值,故采取删除行空值操作。

    1.4.1 删除空值的接口

    • Pandas.dropna(axis=0,how='any')
    • axis: 0 表示是行;1表示是列
    • how:'all'表示只去掉所有值均缺失的行、列;any表示只去掉有缺失值的行、列

    1.4.2 接口运用

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">res_name[14] = res_name[14].dropna(axis=0,how='all')
    res_name[14].tail()
    </pre>

    Div Date HomeTeam AwayTeam FTHG FTAG FTR HTHG HTAG HTR ... BbAv<2.5 BbAH BbAHh BbMxAHH BbAvAHH BbMxAHA BbAvAHA PSCH PSCD PSCA 375 E0 24/05/15 Hull Man United 0.0 0.0 D 0.0 0.0 D ... 1.99 25.0 0.50 1.76 1.71 2.27 2.19 3.20 3.76 2.27 376 E0 24/05/15 Leicester QPR 5.0 1.0 H 2.0 0.0 H ... 2.41 28.0 -1.00 1.98 1.93 1.98 1.93 1.53 4.94 6.13 377 E0 24/05/15 Man City Southampton 2.0 0.0 H 1.0 0.0 H ... 2.66 28.0 -1.00 2.00 1.94 2.03 1.93 1.60 4.35 6.00 378 E0 24/05/15 Newcastle West Ham 2.0 0.0 H 0.0 0.0 D ... 2.25 25.0 -0.50 1.82 1.78 2.20 2.10 1.76 4.01 4.98 379 E0 24/05/15 Stoke Liverpool 6.0 1.0 H 5.0 0.0 H ... 1.99 25.0 0.25 2.07 2.02 1.88 1.85 3.56 3.60 2.17 5 rows × 68 columns

    1.5 删除行数不是 380 的文件名

    考虑到英超一般是 19 个球队,每个球队需要打 20 场球,故把行数不是 380 的数据删除掉,并找到器原 CSV 文件一一对应。

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">for i in range(len(res_name),0,-1):
    # 采用从大到小的遍历方式,然后进行删除不满足条件的。
    if res_name[i-1].shape[0] != 380:
    key = 'res_name[' + str(i) + ']'
    print('删除的数据是:%s年的数据,文件名:%s大小是:%s'%(time_list[i-1],key,res_name[i-1].shape))
    res_name.pop(i-1)
    time_list.pop(i-1)
    continue
    删除的数据是:2018年的数据,文件名:res_name[19]大小是:(304, 62)
    删除的数据是:2004年的数据,文件名:res_name[5]大小是:(335, 57)
    删除的数据是:2003年的数据,文件名:res_name[4]大小是:(335, 57)
    删除的数据是:2002年的数据,文件名:res_name[3]大小是:(316, 48)
    </pre>

    1.6 查看某一个数据集前n行数据

    • 文件名.head(n)
    • n:默认是5,想获取多少行数据就填写数字值。

    读取数据前五行操作:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">res_name[0].head()
    </pre>

    Div Date HomeTeam AwayTeam FTHG FTAG FTR HTHG HTAG HTR ... IWA LBH LBD LBA SBH SBD SBA WHH WHD WHA 0 E0 19/08/00 Charlton Man City 4 0 H 2 0 H ... 2.7 2.20 3.25 2.75 2.20 3.25 2.88 2.10 3.2 3.10 1 E0 19/08/00 Chelsea West Ham 4 2 H 1 0 H ... 4.2 1.50 3.40 6.00 1.50 3.60 6.00 1.44 3.6 6.50 2 E0 19/08/00 Coventry Middlesbrough 1 3 A 1 1 D ... 2.7 2.25 3.20 2.75 2.30 3.20 2.75 2.30 3.2 2.62 3 E0 19/08/00 Derby Southampton 2 2 D 1 2 A ... 3.5 2.20 3.25 2.75 2.05 3.20 3.20 2.00 3.2 3.20 4 E0 19/08/00 Leeds Everton 2 0 H 2 0 H ... 4.5 1.55 3.50 5.00 1.57 3.60 5.00 1.61 3.5 4.50 5 rows × 45 columns

    读取数据前10行:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">res_name[0].head(10)
    </pre>

    Div Date HomeTeam AwayTeam FTHG FTAG FTR HTHG HTAG HTR ... IWA LBH LBD LBA SBH SBD SBA WHH WHD WHA 0 E0 19/08/00 Charlton Man City 4 0 H 2 0 H ... 2.7 2.20 3.25 2.75 2.20 3.25 2.88 2.10 3.20 3.10 1 E0 19/08/00 Chelsea West Ham 4 2 H 1 0 H ... 4.2 1.50 3.40 6.00 1.50 3.60 6.00 1.44 3.60 6.50 2 E0 19/08/00 Coventry Middlesbrough 1 3 A 1 1 D ... 2.7 2.25 3.20 2.75 2.30 3.20 2.75 2.30 3.20 2.62 3 E0 19/08/00 Derby Southampton 2 2 D 1 2 A ... 3.5 2.20 3.25 2.75 2.05 3.20 3.20 2.00 3.20 3.20 4 E0 19/08/00 Leeds Everton 2 0 H 2 0 H ... 4.5 1.55 3.50 5.00 1.57 3.60 5.00 1.61 3.50 4.50 5 E0 19/08/00 Leicester Aston Villa 0 0 D 0 0 D ... 2.5 2.35 3.20 2.60 2.25 3.25 2.75 2.40 3.25 2.50 6 E0 19/08/00 Liverpool Bradford 1 0 H 0 0 D ... 8.0 1.35 4.00 8.00 1.36 4.00 8.00 1.33 4.00 8.00 7 E0 19/08/00 Sunderland Arsenal 1 0 H 0 0 D ... 2.1 4.30 3.20 1.70 3.30 3.10 2.05 3.75 3.00 1.90 8 E0 19/08/00 Tottenham Ipswich 3 1 H 2 1 H ... 4.7 1.45 3.60 6.50 1.50 3.50 6.50 1.44 3.60 6.50 9 E0 20/08/00 Man United Newcastle 2 0 H 1 0 H ... 5.0 1.40 3.75 7.00 1.40 3.75 7.50 1.40 3.75 7.00 10 rows × 45 columns

    读取最后 5 行操作:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">res_name[0].tail()
    </pre>

    Div Date HomeTeam AwayTeam FTHG FTAG FTR HTHG HTAG HTR ... IWA LBH LBD LBA SBH SBD SBA WHH WHD WHA 375 E0 19/05/01 Man City Chelsea 1 2 A 1 1 D ... 1.65 4.0 3.60 1.67 4.20 3.40 1.70 4.00 3.1 1.80 376 E0 19/05/01 Middlesbrough West Ham 2 1 H 2 1 H ... 3.20 1.8 3.25 3.75 1.90 3.20 3.50 1.83 3.4 3.50 377 E0 19/05/01 Newcastle Aston Villa 3 0 H 2 0 H ... 2.90 2.4 3.25 2.50 2.38 3.30 2.50 2.25 3.4 2.60 378 E0 19/05/01 Southampton Arsenal 3 2 H 0 1 A ... 2.35 2.5 3.25 2.37 2.63 3.25 2.30 2.62 3.5 2.20 379 E0 19/05/01 Tottenham Man United 3 1 H 1 1 D ... 2.10 2.6 3.20 2.37 2.60 3.25 2.35 2.62 3.3 2.25 5 rows × 45 columns

    读取最后 4 行操作:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">res_name[0].tail(4)
    </pre>

    Div Date HomeTeam AwayTeam FTHG FTAG FTR HTHG HTAG HTR ... IWA LBH LBD LBA SBH SBD SBA WHH WHD WHA 376 E0 19/05/01 Middlesbrough West Ham 2 1 H 2 1 H ... 3.20 1.8 3.25 3.75 1.90 3.20 3.50 1.83 3.4 3.50 377 E0 19/05/01 Newcastle Aston Villa 3 0 H 2 0 H ... 2.90 2.4 3.25 2.50 2.38 3.30 2.50 2.25 3.4 2.60 378 E0 19/05/01 Southampton Arsenal 3 2 H 0 1 A ... 2.35 2.5 3.25 2.37 2.63 3.25 2.30 2.62 3.5 2.20 379 E0 19/05/01 Tottenham Man United 3 1 H 1 1 D ... 2.10 2.6 3.20 2.37 2.60 3.25 2.35 2.62 3.3 2.25 4 rows × 45 columns

    1.8 获取某一年主场队伍的名称

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">res_name[0]['HomeTeam'].unique()
    array(['Charlton', 'Chelsea', 'Coventry', 'Derby', 'Leeds', 'Leicester',
    'Liverpool', 'Sunderland', 'Tottenham', 'Man United', 'Arsenal',
    'Bradford', 'Ipswich', 'Middlesbrough', 'Everton', 'Man City',
    'Newcastle', 'Southampton', 'West Ham', 'Aston Villa'],
    dtype=object)
    </pre>

    1.9 解析数据集列表头含义

    数据集行数已经固定,一般都是 380 行,而列数可能每年统计指标有变化,不一定相等,而且我们也比较关心列数表表头。由于比较小,可以直接看数据集列数,这样比较快,也可以代码实现,找到最大的列数,然后获取列数的表头进行一般性介绍解释。

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 获取列表头最大的列数,然后获取器参数
    shape_list = [res_name[i].shape[1] for i in range(len(res_name))]
    for i in range(len(res_name)):
    if res_name[i].shape[1] == max(shape_list):
    print('%s年数据是有最大列数:%s,列元素表头:\n %s'%(time_list[i],max(shape_list),res_name[i].columns))
    2012年数据是有最大列数:74,列元素表头:
    Index(['Div', 'Date', 'HomeTeam', 'AwayTeam', 'FTHG', 'FTAG', 'FTR', 'HTHG',
    'HTAG', 'HTR', 'Referee', 'HS', 'AS', 'HST', 'AST', 'HF', 'AF', 'HC',
    'AC', 'HY', 'AY', 'HR', 'AR', 'B365H', 'B365D', 'B365A', 'BWH', 'BWD',
    'BWA', 'GBH', 'GBD', 'GBA', 'IWH', 'IWD', 'IWA', 'LBH', 'LBD', 'LBA',
    'PSH', 'PSD', 'PSA', 'WHH', 'WHD', 'WHA', 'SJH', 'SJD', 'SJA', 'VCH',
    'VCD', 'VCA', 'BSH', 'BSD', 'BSA', 'Bb1X2', 'BbMxH', 'BbAvH', 'BbMxD',
    'BbAvD', 'BbMxA', 'BbAvA', 'BbOU', 'BbMx>2.5', 'BbAv>2.5', 'BbMx<2.5',
    'BbAv<2.5', 'BbAH', 'BbAHh', 'BbMxAHH', 'BbAvAHH', 'BbMxAHA', 'BbAvAHA',
    'PSCH', 'PSCD', 'PSCA'],
    dtype='object')
    </pre>

    我们看到数据包括 Date(比赛的时间),Hometeam(主场队伍名),Awayteam(客场队伍名),FTHG(主场球队全场进球数),HTHG(主场球队半场进球数),FTR(全场比赛结果) 等等,更多关于数据集中特征信息可以参考 数据集特征说明文档 。

    2. 数据清洗和预处理

    我们挑选 Hometeam,Awayteam,FTHG,FTAG,FTR 这五列数据,作为我们的原始的特征数据,后面基于这些原始特征,我们再构造一些新的特征。

    2.1 挑选信息列

    • HomeTeam: 主场球队名
    • AwayTeam: 客场球队名
    • FTHG: 全场 主场球队进球数
    • FTAG: 全场 客场球队进球数
    • FTR: 比赛结果 ( H= 主场赢, D= 平局, A= 客场赢)

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 将挑选的信息放在一个新的列表中
    columns_req = ['HomeTeam','AwayTeam','FTHG','FTAG','FTR']
    playing_statistics = [] # 创造处理后数据名存放处
    playing_data = {} # 键值对存储数据
    for i in range(len(res_name)):
    playing_statistics.append('playing_statistics_'+str(i+1))
    playing_statistics[i] = res_name[i][columns_req]
    print(time_list[i],'playing_statistics['+str(i)+']',playing_statistics[i].shape)
    2000 playing_statistics[0] (380, 5)
    2001 playing_statistics[1] (380, 5)
    2005 playing_statistics[2] (380, 5)
    2006 playing_statistics[3] (380, 5)
    2007 playing_statistics[4] (380, 5)
    2008 playing_statistics[5] (380, 5)
    2009 playing_statistics[6] (380, 5)
    2010 playing_statistics[7] (380, 5)
    2011 playing_statistics[8] (380, 5)
    2012 playing_statistics[9] (380, 5)
    2013 playing_statistics[10] (380, 5)
    2014 playing_statistics[11] (380, 5)
    2015 playing_statistics[12] (380, 5)
    2016 playing_statistics[13] (380, 5)
    2017 playing_statistics[14] (380, 5)
    </pre>

    2.2 分析原始数据

    我们首先预测所有主场球队全都胜利,然后预测所有的客场都会胜利,对结果进行对比分析:

    2.2.1 统计所有主场球队都会胜利的准确率

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def predictions_0(data):
    """
    当我们统计所有主场球队都赢,那么我们预测的结果是什么
    返回值是预测值和实际值
    """
    predictions = []
    for _, game in data.iterrows():

        if game['FTR']=='H':
            predictions.append(1)
        else:
            predictions.append(0)
    # 返回预测结果
    return pd.Series(predictions)
    

    那我们对19年全部主场球队都赢的结果进行预测,获取预测的准确率。

    avg_acc_sum = 0
    for i in range(len(playing_statistics)):
    predictions = predictions_0(playing_statistics[i])
    acc=sum(predictions)/len(playing_statistics[i])
    avg_acc_sum += acc
    print("%s年数据主场全胜预测的准确率是%s"%(time_list[i],acc))
    print('共%s年的平均准确率是:%s'%(len(playing_statistics),avg_acc_sum/len(playing_statistics)))
    2000年数据主场全胜预测的准确率是0.4842105263157895
    2001年数据主场全胜预测的准确率是0.4342105263157895
    2005年数据主场全胜预测的准确率是0.5052631578947369
    2006年数据主场全胜预测的准确率是0.4789473684210526
    2007年数据主场全胜预测的准确率是0.4631578947368421
    2008年数据主场全胜预测的准确率是0.45526315789473687
    2009年数据主场全胜预测的准确率是0.5078947368421053
    2010年数据主场全胜预测的准确率是0.4710526315789474
    2011年数据主场全胜预测的准确率是0.45
    2012年数据主场全胜预测的准确率是0.4368421052631579
    2013年数据主场全胜预测的准确率是0.4710526315789474
    2014年数据主场全胜预测的准确率是0.45263157894736844
    2015年数据主场全胜预测的准确率是0.4131578947368421
    2016年数据主场全胜预测的准确率是0.4921052631578947
    2017年数据主场全胜预测的准确率是0.45526315789473687
    共15年的平均准确率是:0.46473684210526317
    </pre>

    2.2.2 统计所有客场球队都会胜利的准确率

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def predictions_1(data):
    """
    当我们统计所有客场球队都赢,那么我们预测的结果是什么
    返回值是预测值和实际值
    """
    predictions = []
    for _, game in data.iterrows():

        if game['FTR']=='A':
            predictions.append(1)
        else:
            predictions.append(0)
    # 返回预测结果
    return pd.Series(predictions)
    

    那我们对19年客场球队都赢的结果进行预测,获取预测的准确率。

    for i in range(len(playing_statistics)):
    predictions = predictions_1(playing_statistics[i])
    acc=sum(predictions)/len(playing_statistics[i])
    print("%s年数据客场全胜预测的准确率是%s"%(time_list[i],acc))
    2000年数据客场全胜预测的准确率是0.25
    2001年数据客场全胜预测的准确率是0.3
    2005年数据客场全胜预测的准确率是0.29210526315789476
    2006年数据客场全胜预测的准确率是0.2631578947368421
    2007年数据客场全胜预测的准确率是0.2736842105263158
    2008年数据客场全胜预测的准确率是0.2894736842105263
    2009年数据客场全胜预测的准确率是0.2394736842105263
    2010年数据客场全胜预测的准确率是0.23684210526315788
    2011年数据客场全胜预测的准确率是0.30526315789473685
    2012年数据客场全胜预测的准确率是0.2789473684210526
    2013年数据客场全胜预测的准确率是0.3236842105263158
    2014年数据客场全胜预测的准确率是0.3026315789473684
    2015年数据客场全胜预测的准确率是0.30526315789473685
    2016年数据客场全胜预测的准确率是0.2868421052631579
    2017年数据客场全胜预测的准确率是0.28421052631578947
    </pre>

    综上比较:我们可以看出主场胜利的概率相对于输和平局来说,确实概率要大。

    2.3 我们想知道 Arsenal 作为主场队伍时,他们的表现,如何求出 2005-06 所有比赛累计进球数 ?

    我们知道 2005-06 年数据在 playing_statistics[2] 中:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def score(data):
    """ Arsenal作为主场队伍时,累计进球数 """
    scores=[]
    for _,game in data.iterrows():
    if game['HomeTeam']=='Arsenal':
    scores.append(game['FTHG'])
    return np.sum(scores)
    Arsenal_score=score(playing_statistics[2])
    print("Arsenal作为主场队伍在2005年时,累计进球数:%s"%(Arsenal_score))
    Arsenal 作为主场队伍在2005年时,累计进球数:48
    </pre>

    2.4 我们想知道各个球队作为主场队伍时,他们的表现如何 ?

    先试试求 2005-06 所有比赛各个球队累计进球数。

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">print(playing_statistics[5].groupby('HomeTeam').sum()['FTHG'])
    HomeTeam
    Arsenal 31
    Aston Villa 27
    Blackburn 22
    Bolton 21
    Chelsea 33
    Everton 31
    Fulham 28
    Hull 18
    Liverpool 41
    Man City 40
    Man United 43
    Middlesbrough 17
    Newcastle 24
    Portsmouth 26
    Stoke 22
    Sunderland 21
    Tottenham 21
    West Brom 26
    West Ham 23
    Wigan 17
    Name: FTHG, dtype: int64
    </pre>

    3. 特征工程

    特征工程指的是把原始数据转变为模型的训练数据的过程,它的目的就是获取更好的训练数据特征,得到更好的训练模型。特征工程能使得模型的性能得到提升,有时甚至在简单的模型上也能取得不错的效果。特征工程在机器学习中占有非常重要的作用,一般认为括特征构建、特征提取、特征选择三大部分。

    3.1 构造特征

    因为这个比赛是一年一个赛季,是有先后顺序的,那我们就可以统计到截止到本场比赛之前,整个赛季内,主客场队伍的净胜球的数量。那么对于每一个赛季的每一周,都统计出每个球队到本周为止累计的进球数和丢球数之差,也就是净胜球的数量。

    3.1.1 计算每个队周累计净胜球数量

    处理后的数据,我们可以通过看某一年的某几条数据来体现,比如:05-06 年的后五条数据

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def get_goals_diff(playing_stat):
    # 创建一个字典,每个 team 的 name 作为 key
    teams = {}
    for i in playing_stat.groupby('HomeTeam').mean().T.columns:
    teams[i] = []
    # 对于每一场比赛
    for i in range(len(playing_stat)):
    # 全场比赛,主场队伍的进球数
    HTGS = playing_stat.iloc[i]['FTHG']
    # 全场比赛,客场队伍的进球数
    ATGS = playing_stat.iloc[i]['FTAG']
    # 把主场队伍的净胜球数添加到 team 这个 字典中对应的主场队伍下
    teams[playing_stat.iloc[i].HomeTeam].append(HTGS-ATGS)
    # 把客场队伍的净胜球数添加到 team 这个 字典中对应的客场队伍下
    teams[playing_stat.iloc[i].AwayTeam].append(ATGS-HTGS)
    # 创建一个 GoalsDifference 的 dataframe
    # 行是 team 列是 matchweek,
    # 39解释:19个球队,每个球队分主场客场2次,共38个赛次,但是range取不到最后一个值,故38+1=39
    GoalsDifference = pd.DataFrame(data=teams, index = [i for i in range(1,39)]).T
    GoalsDifference[0] = 0
    # 累加每个队的周比赛的净胜球数
    for i in range(2,39):
    GoalsDifference[i] = GoalsDifference[i] + GoalsDifference[i-1]
    return GoalsDifference
    def get_gss(playing_stat):
    # 得到净胜球数统计
    GD = get_goals_diff(playing_stat)
    j = 0
    # 主客场的净胜球数
    HTGD = []
    ATGD = []
    # 全年一共380场比赛
    for i in range(380):
    ht = playing_stat.iloc[i].HomeTeam
    at = playing_stat.iloc[i].AwayTeam
    HTGD.append(GD.loc[ht][j])
    ATGD.append(GD.loc[at][j])
    if ((i + 1)% 10) == 0:
    j = j + 1
    # 把每个队的 HTGD ATGD 信息补充到 dataframe 中
    playing_stat.loc[:,'HTGD'] = HTGD
    playing_stat.loc[:,'ATGD'] = ATGD
    return playing_stat
    for i in range(len(playing_statistics)):
    playing_statistics[i] = get_gss(playing_statistics[i])

    查看构造特征后的05-06年的后五条数据

    playing_statistics[2].tail()
    </pre>

    HomeTeam AwayTeam FTHG FTAG FTR HTGD ATGD 375 Fulham Middlesbrough 1 0 H -11 -9 376 Man United Charlton 4 0 H 34 -10 377 Newcastle Chelsea 1 0 H 4 51 378 Portsmouth Liverpool 1 3 A -23 30 379 West Ham Tottenham 2 1 H -4 16 通过以上数据:我们发现 376 行数据的特点, 截止到这一场比赛之前,本赛季主场曼联队的净胜球数是 34 , 客场查尔顿队的净胜球数是 -10 。

    3.1.2 统计主客场队伍到当前比赛周的累计得分

    统计整个赛季主客场队伍截止到当前比赛周的累计得分。一场比赛胜利计 3 分, 平局计 1 分,输了计 0 分。我们根据本赛季本周之前的比赛结果来统计这个值。我们继续观看 05-06 年的后五条数据:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 把比赛结果转换为得分,赢得三分,平局得一分,输不得分
    def get_points(result):
    if result == 'W':
    return 3
    elif result == 'D':
    return 1
    else:
    return 0

    def get_cuml_points(matchres):
    matchres_points = matchres.applymap(get_points)
    for i in range(2,39):
    matchres_points[i] = matchres_points[i] + matchres_points[i-1]
    matchres_points.insert(column =0, loc = 0, value = [0*i for i in range(20)])
    return matchres_points
    def get_matchres(playing_stat):
    # 创建一个字典,每个 team 的 name 作为 key
    teams = {}
    for i in playing_stat.groupby('HomeTeam').mean().T.columns:
    teams[i] = []
    # 把比赛结果分别记录在主场队伍和客场队伍中
    # H:代表 主场 赢
    # A:代表 客场 赢
    # D:代表 平局
    for i in range(len(playing_stat)):
    if playing_stat.iloc[i].FTR == 'H':
    # 主场 赢,则主场记为赢,客场记为输
    teams[playing_stat.iloc[i].HomeTeam].append('W')
    teams[playing_stat.iloc[i].AwayTeam].append('L')
    elif playing_stat.iloc[i].FTR == 'A':
    # 客场 赢,则主场记为输,客场记为赢
    teams[playing_stat.iloc[i].AwayTeam].append('W')
    teams[playing_stat.iloc[i].HomeTeam].append('L')
    else:
    # 平局
    teams[playing_stat.iloc[i].AwayTeam].append('D')
    teams[playing_stat.iloc[i].HomeTeam].append('D')
    return pd.DataFrame(data=teams, index = [i for i in range(1,39)]).T
    def get_agg_points(playing_stat):
    matchres = get_matchres(playing_stat)
    cum_pts = get_cuml_points(matchres)
    HTP = []
    ATP = []
    j = 0
    for i in range(380):
    ht = playing_stat.iloc[i].HomeTeam
    at = playing_stat.iloc[i].AwayTeam
    HTP.append(cum_pts.loc[ht][j])
    ATP.append(cum_pts.loc[at][j])
    if ((i + 1)% 10) == 0:
    j = j + 1
    # 主场累计得分
    playing_stat.loc[:,'HTP'] = HTP
    # 客场累计得分
    playing_stat.loc[:,'ATP'] = ATP
    return playing_stat
    for i in range(len(playing_statistics)):
    playing_statistics[i] = get_agg_points(playing_statistics[i])

    查看构造特征后的05-06年的后五条数据

    playing_statistics[2].tail()
    </pre>

    HomeTeam AwayTeam FTHG FTAG FTR HTGD ATGD HTP ATP 375 Fulham Middlesbrough 1 0 H -11 -9 45 45 376 Man United Charlton 4 0 H 34 -10 80 47 377 Newcastle Chelsea 1 0 H 4 51 55 91 378 Portsmouth Liverpool 1 3 A -23 30 38 79 379 West Ham Tottenham 2 1 H -4 16 52 65 我们处理得到 HTP (本赛季主场球队截止到本周的累计得分), ATP (本赛季客场球队截止到本周的累计得分)。

    我们再看 376 行,截止到这一场比赛,本赛季,曼联队一共积了80分, 查尔顿队积了 47 分。

    3.1.3 统计某支队伍最近三场比赛的表现

    前面我们构造的特征反映了一只队伍本赛季的历史总表现,我们看看队伍在最近三场比赛的表现。

    我们用:

    HM1 代表主场球队上一次比赛的输赢,

    AM1 代表客场球队上一次比赛是输赢。

    同理,HM2 AM2 就是上上次比赛的输赢, HM3 AM3 就是上上上次比赛的输赢。

    我们继续观看处理后 05-06 年的后 5 五条数据:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def get_form(playing_stat,num):
    form = get_matchres(playing_stat)
    form_final = form.copy()
    for i in range(num,39):
    form_final[i] = ''
    j = 0
    while j < num:
    form_final[i] += form[i-j]
    j += 1
    return form_final
    def add_form(playing_stat,num):
    form = get_form(playing_stat,num)
    # M 代表 unknown, 因为没有那么多历史
    h = ['M' for i in range(num * 10)]
    a = ['M' for i in range(num * 10)]
    j = num
    for i in range((num*10),380):
    ht = playing_stat.iloc[i].HomeTeam
    at = playing_stat.iloc[i].AwayTeam
    past = form.loc[ht][j]
    h.append(past[num-1])
    past = form.loc[at][j]
    a.append(past[num-1])
    if ((i + 1)% 10) == 0:
    j = j + 1
    playing_stat['HM' + str(num)] = h
    playing_stat['AM' + str(num)] = a
    return playing_stat
    def add_form_df(playing_statistics):
    playing_statistics = add_form(playing_statistics,1)
    playing_statistics = add_form(playing_statistics,2)
    playing_statistics = add_form(playing_statistics,3)
    return playing_statistics
    for i in range(len(playing_statistics)):
    playing_statistics[i] = add_form_df(playing_statistics[i])

    查看构造特征后的05-06年的后5五条数据

    playing_statistics[2].tail()
    </pre>

    HomeTeam AwayTeam FTHG FTAG FTR HTGD ATGD HTP ATP HM1 AM1 HM2 AM2 HM3 AM3 375 Fulham Middlesbrough 1 0 H -11 -9 45 45 L D W D W L 376 Man United Charlton 4 0 H 34 -10 80 47 D L L L W W 377 Newcastle Chelsea 1 0 H 4 51 55 91 D L W W W W 378 Portsmouth Liverpool 1 3 A -23 30 38 79 W W W W L W 379 West Ham Tottenham 2 1 H -4 16 52 65 W W L D L L 3.1.4 加入比赛周特征(第几个比赛周)

    然后我们把比赛周的信息也放在里面,也就是这一场比赛发生在第几个比赛周。

    特征构造后的结果,我们可以直接查看 05-06 年的后 5 条数据:

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def get_mw(playing_stat):
    j = 1
    MatchWeek = []
    for i in range(380):
    MatchWeek.append(j)
    if ((i + 1)% 10) == 0:
    j = j + 1
    playing_stat['MW'] = MatchWeek
    return playing_stat
    for i in range(len(playing_statistics)):
    playing_statistics[i] = get_mw(playing_statistics[i])

    查看构造特征后的05-06年的后五条数据

    playing_statistics[2].tail()
    </pre>

    HomeTeam AwayTeam FTHG FTAG FTR HTGD ATGD HTP ATP HM1 AM1 HM2 AM2 HM3 AM3 MW 375 Fulham Middlesbrough 1 0 H -11 -9 45 45 L D W D W L 38 376 Man United Charlton 4 0 H 34 -10 80 47 D L L L W W 38 377 Newcastle Chelsea 1 0 H 4 51 55 91 D L W W W W 38 378 Portsmouth Liverpool 1 3 A -23 30 38 79 W W W W L W 38 379 West Ham Tottenham 2 1 H -4 16 52 65 W W L D L L 38 3.1.5 合并比赛的信息

    我们打算把数据集比赛的信息都合并到一个表里面,然后我们把我们刚才计算得到的这些得分数据,净胜球数据除以周数,就得到了周平均后的值。结果就可以通过查看构造特征后数据集的后 5 条数据。

    <pre spellcheck="false" style="box-sizing: border-box; margin: 5px 0px; padding: 5px 10px; border: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-numeric: inherit; font-variant-east-asian: inherit; font-weight: 400; font-stretch: inherit; font-size: 16px; line-height: inherit; font-family: inherit; vertical-align: baseline; cursor: text; counter-reset: list-1 0 list-2 0 list-3 0 list-4 0 list-5 0 list-6 0 list-7 0 list-8 0 list-9 0; background-color: rgb(240, 240, 240); border-radius: 3px; white-space: pre-wrap; color: rgb(34, 34, 34); letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 将各个DataFrame表合并在一张表中
    playing_stat = pd.concat(playing_statistics, ignore_index=True)

    HTGD, ATGD ,HTP, ATP的值 除以 week 数,得到平均分

    cols = ['HTGD','ATGD','HTP','ATP']
    playing_stat.MW = playing_stat.MW.astype(float)
    for col in cols:
    playing_stat[col] = playing_stat[col] / playing_stat.MW

    查看构造特征后数据集的后5五条数据

    playing_stat.tail()
    </pre>

    HomeTeam AwayTeam FTHG FTAG FTR HTGD ATGD HTP ATP HM1 AM1 HM2 AM2 HM3 AM3 MW 5695 Newcastle Chelsea 3.0 0.0 H -0.289474 0.710526 1.078947 1.842105 L D L W L W 38.0 5696 Southampton Man City 0.0 1.0 A -0.473684 2.052632 0.947368 2.552632 W W D D W W 38.0 5697 Swansea Stoke 1.0 2.0 A -0.710526 -0.894737 0.868421 0.789474 L L L D L D 38.0 5698 Tottenham Leicester 5.0 4.0 H 0.973684 -0.078947 1.947368 1.236842 W W L L W L 38.0 5699 West Ham Everton 3.0 1.0 H -0.578947 -0.315789 1.026316 1.289474 D D W W L W 38.0 我们看到数据集最后一行的行数是 5699 ,加上第一行为 0 行,则一共 5700 条数据;我们总共统计了 15 年的数据,每一年有 380 条数据,计算后发现我们统计后的数据集大小是准确的。

    相关文章

      网友评论

        本文标题:采用 Python 机器学习预测足球比赛结果!买谁赢就谁赢!

        本文链接:https://www.haomeiwen.com/subject/wlzmoqtx.html