Dixon and Coles

[1]:
import sys

sys.path.append("../../")

import penaltyblog as pb

Get data from football-data.co.uk

[2]:
fb = pb.scrapers.FootballData("ENG Premier League", "2019-2020")
df = fb.get_fixtures()

df.head()
[2]:
competition season datetime div date time team_home team_away fthg ftag ... b365_cahh b365_caha pcahh pcaha max_cahh max_caha avg_cahh avg_caha goals_home goals_away
id
1565308800---liverpool---norwich ENG Premier League 2019-2020 2019-08-09 20:00:00 E0 2019-08-09 20:00 Liverpool Norwich 4 1 ... 1.91 1.99 1.94 1.98 1.99 2.07 1.90 1.99 4 1
1565395200---bournemouth---sheffield_united ENG Premier League 2019-2020 2019-08-10 15:00:00 E0 2019-08-10 15:00 Bournemouth Sheffield United 1 1 ... 1.95 1.95 1.98 1.95 2.00 1.96 1.96 1.92 1 1
1565395200---burnley---southampton ENG Premier League 2019-2020 2019-08-10 15:00:00 E0 2019-08-10 15:00 Burnley Southampton 3 0 ... 1.87 2.03 1.89 2.03 1.90 2.07 1.86 2.02 3 0
1565395200---crystal_palace---everton ENG Premier League 2019-2020 2019-08-10 15:00:00 E0 2019-08-10 15:00 Crystal Palace Everton 0 0 ... 1.82 2.08 1.97 1.96 2.03 2.08 1.96 1.93 0 0
1565395200---tottenham---aston_villa ENG Premier League 2019-2020 2019-08-10 17:30:00 E0 2019-08-10 17:30 Tottenham Aston Villa 3 1 ... 2.10 1.70 2.18 1.77 2.21 1.87 2.08 1.80 3 1

5 rows × 111 columns

Train the model

[3]:
clf = pb.models.DixonColesGoalModel(
    df["goals_home"], df["goals_away"], df["team_home"], df["team_away"]
)
clf.fit()

The model’s parameters

[4]:
clf
[4]:
Module: Penaltyblog

Model: Dixon and Coles

Number of parameters: 42
Log Likelihood: -1057.16
AIC: 2198.319

Team                 Attack               Defence
------------------------------------------------------------
Arsenal              1.134                -0.939
Aston Villa          0.843                -0.619
Bournemouth          0.812                -0.652
Brighton             0.781                -0.832
Burnley              0.874                -0.917
Chelsea              1.341                -0.81
Crystal Palace       0.54                 -0.928
Everton              0.904                -0.798
Leicester            1.306                -1.077
Liverpool            1.539                -1.288
Man City             1.72                 -1.213
Man United           1.283                -1.217
Newcastle            0.756                -0.773
Norwich              0.386                -0.524
Sheffield United     0.757                -1.171
Southampton          1.046                -0.729
Tottenham            1.216                -0.951
Watford              0.712                -0.664
West Ham             1.012                -0.693
Wolves               1.037                -1.12
------------------------------------------------------------
Home Advantage: 0.231
Rho: -0.079
[5]:
clf.get_params()
[5]:
{'attack_Arsenal': 1.1341865177762285,
 'attack_Aston Villa': 0.8428530080228543,
 'attack_Bournemouth': 0.8120403901309736,
 'attack_Brighton': 0.7808625592284577,
 'attack_Burnley': 0.8735990924845769,
 'attack_Chelsea': 1.340685364571421,
 'attack_Crystal Palace': 0.540289929985007,
 'attack_Everton': 0.9040391275578089,
 'attack_Leicester': 1.3057973747311051,
 'attack_Liverpool': 1.5388075144975972,
 'attack_Man City': 1.7197213689727928,
 'attack_Man United': 1.2833539229945745,
 'attack_Newcastle': 0.7560462391368982,
 'attack_Norwich': 0.38635937830680633,
 'attack_Sheffield United': 0.7571523352515713,
 'attack_Southampton': 1.0462746462988073,
 'attack_Tottenham': 1.216439560492832,
 'attack_Watford': 0.7122177934411291,
 'attack_West Ham': 1.0118517568580763,
 'attack_Wolves': 1.0374221192548183,
 'defence_Arsenal': -0.9388906422952455,
 'defence_Aston Villa': -0.6190197176844375,
 'defence_Bournemouth': -0.6519855379159416,
 'defence_Brighton': -0.8319679353511403,
 'defence_Burnley': -0.9169866533049907,
 'defence_Chelsea': -0.8096432828942898,
 'defence_Crystal Palace': -0.9276726140616492,
 'defence_Everton': -0.7977905220617109,
 'defence_Leicester': -1.0774381274274807,
 'defence_Liverpool': -1.2882869615601673,
 'defence_Man City': -1.2127279738256183,
 'defence_Man United': -1.2167286266767237,
 'defence_Newcastle': -0.7732671939429236,
 'defence_Norwich': -0.5236073026183325,
 'defence_Sheffield United': -1.1712568842023234,
 'defence_Southampton': -0.7286812539890076,
 'defence_Tottenham': -0.9506798704672896,
 'defence_Watford': -0.6644785296965087,
 'defence_West Ham': -0.6929137366167742,
 'defence_Wolves': -1.1199735644750717,
 'home_advantage': 0.2311245551328041,
 'rho': -0.07853233375103048}

Predict Match Outcomes

[6]:
probs = clf.predict("Liverpool", "Wolves")
probs
[6]:
Module: Penaltyblog

Class: FootballProbabilityGrid

Home Goal Expectation: 1.9154613455938239
Away Goal Expectation: 0.7781275343757059

Home Win: 0.6343570672571542
Draw: 0.22868509470199844
Away Win: 0.13695783584981738

1x2 Probabilities

[7]:
probs.home_draw_away
[7]:
[0.6343570672571542, 0.22868509470199844, 0.13695783584981738]
[8]:
probs.home_win
[8]:
0.6343570672571542
[9]:
probs.draw
[9]:
0.22868509470199844
[10]:
probs.away_win
[10]:
0.13695783584981738

Probablity of Total Goals >1.5

[11]:
probs.total_goals("over", 1.5)
[11]:
0.7580909443325337

Probability of Asian Handicap 1.5

[12]:
probs.asian_handicap("home", 1.5)
[12]:
0.38896867360115095

Probability of both teams scoring

[13]:
probs.both_teams_to_score
[13]:
0.46901574333181895