Poisson

[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 a basic poisson model

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

The model’s parameters

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

Model: Poisson

Number of parameters: 41
Log Likelihood: -1057.712
AIC: 2197.424

Team                 Attack               Defence
------------------------------------------------------------
Arsenal              1.133                -0.937
Aston Villa          0.84                 -0.618
Bournemouth          0.813                -0.65
Brighton             0.777                -0.837
Burnley              0.87                 -0.91
Chelsea              1.349                -0.806
Crystal Palace       0.543                -0.922
Everton              0.899                -0.795
Leicester            1.306                -1.084
Liverpool            1.536                -1.283
Man City             1.721                -1.206
Man United           1.286                -1.216
Newcastle            0.755                -0.766
Norwich              0.391                -0.521
Sheffield United     0.761                -1.163
Southampton          1.052                -0.719
Tottenham            1.218                -0.953
Watford              0.706                -0.669
West Ham             1.014                -0.688
Wolves               1.031                -1.125
------------------------------------------------------------
Home Advantage: 0.229
[5]:
clf.get_params()
[5]:
{'attack_Arsenal': 1.1331236899973345,
 'attack_Aston Villa': 0.8398888104788944,
 'attack_Bournemouth': 0.8130897663316354,
 'attack_Brighton': 0.7765248253257214,
 'attack_Burnley': 0.8703023371771994,
 'attack_Chelsea': 1.3487338919001544,
 'attack_Crystal Palace': 0.5425422408745968,
 'attack_Everton': 0.8994386622804366,
 'attack_Leicester': 1.305683340822444,
 'attack_Liverpool': 1.536142023201564,
 'attack_Man City': 1.721273889006884,
 'attack_Man United': 1.2855301627562425,
 'attack_Newcastle': 0.754538349388783,
 'attack_Norwich': 0.3911250522596789,
 'attack_Sheffield United': 0.7614768317608919,
 'attack_Southampton': 1.0516111981282654,
 'attack_Tottenham': 1.2177895314312077,
 'attack_Watford': 0.7064633632379288,
 'attack_West Ham': 1.0135085594841655,
 'attack_Wolves': 1.0312134741439425,
 'defence_Arsenal': -0.9373593152185443,
 'defence_Aston Villa': -0.6183887167614771,
 'defence_Bournemouth': -0.6497780016893445,
 'defence_Brighton': -0.8366644455845825,
 'defence_Burnley': -0.9096445581199665,
 'defence_Chelsea': -0.8056794617596451,
 'defence_Crystal Palace': -0.9217234584764492,
 'defence_Everton': -0.7950830265711245,
 'defence_Leicester': -1.0841115587982018,
 'defence_Liverpool': -1.283371292184721,
 'defence_Man City': -1.2063235545625164,
 'defence_Man United': -1.2156312104034752,
 'defence_Newcastle': -0.766019714032436,
 'defence_Norwich': -0.520671121600944,
 'defence_Sheffield United': -1.1626929246095525,
 'defence_Southampton': -0.7187488659558111,
 'defence_Tottenham': -0.953348247236947,
 'defence_Watford': -0.6693854533833772,
 'defence_West Ham': -0.6878737389877748,
 'defence_Wolves': -1.1252407856242987,
 'home_advantage': 0.2292519839991387}

Predict Match Outcomes

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

Class: FootballProbabilityGrid

Home Goal Expectation: 1.8967714833577352
Away Goal Expectation: 0.7771220845059058

Home Win: 0.6385321493320355
Draw: 0.21487353680172425
Away Win: 0.1465943119417152

1x2 Probabilities

[7]:
probs.home_draw_away
[7]:
[0.6385321493320355, 0.21487353680172425, 0.1465943119417152]
[8]:
probs.home_win
[8]:
0.6385321493320355
[9]:
probs.draw
[9]:
0.21487353680172425
[10]:
probs.away_win
[10]:
0.1465943119417152

Probablity of Total Goals >1.5

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

Probability of Asian Handicap 1.5

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

Probability of both teams scoring

[13]:
probs.both_teams_to_score
[13]:
0.45920366069754437