This document summarises the forecast outcomes for the fourth weekly set of forecasts for English football match outcomes, following on from recent weeks, and it provides outcomes for forecasts of matches over the last week as detailed in this document.
Two sets of forecasts are constructed, one using a simple linear regression method for a dependent variable taking the values 0 for an away win, 0.5 for a draw, and 1 for a home win. This linear regression method only yields a number which can be interpreted as a probability of an outcome occurring. The second, ordered logit method, treats each outcome in an ordered manner, from away win, to draw, to home win, and estimates a probability for each outcome.
The purpose of this document is to evaluate these forecasts, and begin to form a longer-term narrative about them.
To consider outcomes; we must load up the specific outcomes file for matches forecast over the weekend:
dates <- c("2015-01-30","2015-02-06","2015-02-13","2015-02-20","2015-02-27")
date.1 <- dates[NROW(dates)]
recent.forecast.outcomes <- read.csv(paste("forecast_outcomes_",date.1,".csv",sep=""),stringsAsFactors=F)
forecast.matches <- read.csv(paste("forecasts_",date.1,".csv",sep=""))
forecast.matches <- forecast.matches[is.na(forecast.matches$outcome)==F,]
forecast.outcomes <- merge(forecast.matches[,c("match_id","outcome","Ph","Pd","Pa")],
recent.forecast.outcomes,by=c("match_id"),
suffixes=c(".forc",".final"))
forecast.outcomes <- forecast.outcomes[is.na(forecast.outcomes$outcome.final)==F,]
#all.forecast.outcomes <- data.frame()
#for(i in dates) {
# temp.0 <- read.csv(paste(loc2,"forecast_outcomes_",i,".csv",sep=""),stringsAsFactors=F)
# temp.1 <- read.csv(paste(loc2,"forecasts_",i,".csv",sep=""))
# temp.1 <- temp.1[is.na(temp.1$outcome)==F,]
# temp.2 <- merge(temp.1[,c("match_id","outcome","Ph","Pd","Pa")],
# temp.0,by=c("match_id"),
# suffixes=c(".forc",".final"))
# forecast.outcomes <- rbind(temp.2[is.na(temp.2$outcome.final)==F,],forecast.outcomes)
#}
We also load up previous weeks’ forecasts and outcomes in order that we can begin to determine trends over time. This week was one particularly filled with surprise results, but that does not necessarily mean our forecast model need be amended. More, it reflects that football is intrinsically a very uncertain game. This, of course, is not to say that the model cannot be improved upon.
First, our Premier League forecasts:
prem.matches <- forecast.outcomes[forecast.outcomes$division=="English Premier",]
prem.matches$id <- 1:NROW(prem.matches)
par(mar=c(9,4,4,5)+.1)
plot(prem.matches$id,prem.matches$outcome.forc,xaxt="n",xlab="",ylim=range(0,1),
main="Forecasts of Weekend Premier League Matches",
ylab="Probability of Outcome")
lines(prem.matches$id,prem.matches$Ph,col=2,pch=15,type="p")
lines(prem.matches$id,prem.matches$Pd,col=3,pch=16,type="p")
lines(prem.matches$id,prem.matches$Pa,col=4,pch=17,type="p")
legend("topleft",ncol=4,pch=c(1,15,16,17),col=c(1:4),
legend=c("OLS","OL (home)","OL (draw)","OL (away)"),bty="n")
abline(h=0.5,lty=2)
abline(h=0.6,lty=3)
abline(h=0.7,lty=2)
abline(h=0.4,lty=3)
for(i in 1:NROW(prem.matches)) {
if(prem.matches$outcome.final[i]==1) {
lines(prem.matches$id[i],prem.matches$outcome.final[i],col=2,type="p",pch=0)
lines(rep(i,2),c(prem.matches$Ph[i],prem.matches$outcome.final[i]),type="l",lty=2,col="red")
} else if (prem.matches$outcome.final[i]==0.5) {
lines(prem.matches$id[i],prem.matches$outcome.final[i],col=3,type="p",pch=1)
lines(rep(i,2),c(prem.matches$Pd[i],prem.matches$outcome.final[i]),type="l",lty=2,col="green")
} else {
lines(prem.matches$id[i],prem.matches$outcome.final[i],col=4,type="p",pch=2)
lines(rep(i,2),c(prem.matches$Pa[i],prem.matches$outcome.final[i]),type="l",lty=2,col="blue")
}
}
axis(1,at=prem.matches$id,labels=paste(prem.matches$team1,prem.matches$team2,sep=" v "),las=2,cex.axis=0.65)
Outcomes are hollowed variants of their predicted probabilities; red empty circles are home wins, marked on at 1, green empty circles are draws, marked on at 0.5, and blue empty triangles are away wins. All are linked to their associated probability. This drawing doesn’t quite reflect actual forecast errors since each outcome is 1 if it happened, but nonetheless illustrates the weekend’s outcomes.
Next, our Championship forecasts:
champ.matches <- forecast.outcomes[forecast.outcomes$division=="English Championship",]
champ.matches$id <- 1:NROW(champ.matches)
par(mar=c(9,4,4,5)+.1)
plot(champ.matches$id,champ.matches$outcome.forc,xaxt="n",xlab="",ylim=range(0,1),
main="Forecasts of Weekend Championship Matches",
ylab="Probability of Outcome")
lines(champ.matches$id,champ.matches$Ph,col=2,pch=15,type="p")
lines(champ.matches$id,champ.matches$Pd,col=3,pch=16,type="p")
lines(champ.matches$id,champ.matches$Pa,col=4,pch=17,type="p")
legend("topleft",ncol=4,pch=c(1,15,16,17),col=c(1:4),
legend=c("OLS","OL (home)","OL (draw)","OL (away)"),bty="n")
abline(h=0.5,lty=2)
abline(h=0.6,lty=3)
abline(h=0.7,lty=2)
abline(h=0.4,lty=3)
for(i in 1:NROW(champ.matches)) {
if(champ.matches$outcome.final[i]==1) {
lines(champ.matches$id[i],champ.matches$outcome.final[i],col=2,type="p",pch=0)
lines(rep(i,2),c(champ.matches$Ph[i],champ.matches$outcome.final[i]),type="l",lty=2,col="red")
} else if (champ.matches$outcome.final[i]==0.5) {
lines(champ.matches$id[i],champ.matches$outcome.final[i],col=3,type="p",pch=1)
lines(rep(i,2),c(champ.matches$Pd[i],champ.matches$outcome.final[i]),type="l",lty=2,col="green")
} else {
lines(champ.matches$id[i],champ.matches$outcome.final[i],col=4,type="p",pch=2)
lines(rep(i,2),c(champ.matches$Pa[i],champ.matches$outcome.final[i]),type="l",lty=2,col="blue")
}
}
axis(1,at=champ.matches$id,labels=paste(champ.matches$team1,champ.matches$team2,sep=" v "),las=2,cex.axis=0.65)
Next, our League One forecasts:
lg1.matches <- forecast.outcomes[forecast.outcomes$division=="English League One",]
lg1.matches$id <- 1:NROW(lg1.matches)
par(mar=c(9,4,4,5)+.1)
plot(lg1.matches$id,lg1.matches$outcome.forc,xaxt="n",xlab="",ylim=range(0,1),
main="Forecasts of Weekend League One Matches",
ylab="Probability of Outcome")
lines(lg1.matches$id,lg1.matches$Ph,col=2,pch=15,type="p")
lines(lg1.matches$id,lg1.matches$Pd,col=3,pch=16,type="p")
lines(lg1.matches$id,lg1.matches$Pa,col=4,pch=17,type="p")
legend("topleft",ncol=4,pch=c(1,15,16,17),col=c(1:4),
legend=c("OLS","OL (home)","OL (draw)","OL (away)"),bty="n")
abline(h=0.5,lty=2)
abline(h=0.6,lty=3)
abline(h=0.7,lty=2)
abline(h=0.4,lty=3)
for(i in 1:NROW(lg1.matches)) {
if(lg1.matches$outcome.final[i]==1) {
lines(lg1.matches$id[i],lg1.matches$outcome.final[i],col=2,type="p",pch=0)
lines(rep(i,2),c(lg1.matches$Ph[i],lg1.matches$outcome.final[i]),type="l",lty=2,col="red")
} else if (lg1.matches$outcome.final[i]==0.5) {
lines(lg1.matches$id[i],lg1.matches$outcome.final[i],col=3,type="p",pch=1)
lines(rep(i,2),c(lg1.matches$Pd[i],lg1.matches$outcome.final[i]),type="l",lty=2,col="green")
} else {
lines(lg1.matches$id[i],lg1.matches$outcome.final[i],col=4,type="p",pch=2)
lines(rep(i,2),c(lg1.matches$Pa[i],lg1.matches$outcome.final[i]),type="l",lty=2,col="blue")
}
}
axis(1,at=lg1.matches$id,labels=paste(lg1.matches$team1,lg1.matches$team2,sep=" v "),las=2,cex.axis=0.65)
Next, our League Two forecasts:
lg2.matches <- forecast.outcomes[forecast.outcomes$division=="English League Two",]
lg2.matches$id <- 1:NROW(lg2.matches)
par(mar=c(9,4,4,5)+.1)
plot(lg2.matches$id,lg2.matches$outcome.forc,xaxt="n",xlab="",ylim=range(0,1),
main="Forecasts of Weekend League Two Matches",
ylab="Probability of Outcome")
lines(lg2.matches$id,lg2.matches$Ph,col=2,pch=15,type="p")
lines(lg2.matches$id,lg2.matches$Pd,col=3,pch=16,type="p")
lines(lg2.matches$id,lg2.matches$Pa,col=4,pch=17,type="p")
legend("topleft",ncol=4,pch=c(1,15,16,17),col=c(1:4),
legend=c("OLS","OL (home)","OL (draw)","OL (away)"),bty="n")
abline(h=0.5,lty=2)
abline(h=0.6,lty=3)
abline(h=0.7,lty=2)
abline(h=0.4,lty=3)
for(i in 1:NROW(lg2.matches)) {
if(lg2.matches$outcome.final[i]==1) {
lines(lg2.matches$id[i],lg2.matches$outcome.final[i],col=2,type="p",pch=0)
lines(rep(i,2),c(lg2.matches$Ph[i],lg2.matches$outcome.final[i]),type="l",lty=2,col="red")
} else if (lg2.matches$outcome.final[i]==0.5) {
lines(lg2.matches$id[i],lg2.matches$outcome.final[i],col=3,type="p",pch=1)
lines(rep(i,2),c(lg2.matches$Pd[i],lg2.matches$outcome.final[i]),type="l",lty=2,col="green")
} else {
lines(lg2.matches$id[i],lg2.matches$outcome.final[i],col=4,type="p",pch=2)
lines(rep(i,2),c(lg2.matches$Pa[i],lg2.matches$outcome.final[i]),type="l",lty=2,col="blue")
}
}
axis(1,at=lg2.matches$id,labels=paste(lg2.matches$team1,lg2.matches$team2,sep=" v "),las=2,cex.axis=0.65)
Next, our Football Conference forecasts:
conf.matches <- forecast.outcomes[forecast.outcomes$division=="Football Conference",]
conf.matches$id <- 1:NROW(conf.matches)
par(mar=c(9,4,4,5)+.1)
plot(conf.matches$id,conf.matches$outcome.forc,xaxt="n",xlab="",ylim=range(0,1),
main="Forecasts of Weekend Football Conference Matches",
ylab="Probability of Outcome")
lines(conf.matches$id,conf.matches$Ph,col=2,pch=15,type="p")
lines(conf.matches$id,conf.matches$Pd,col=3,pch=16,type="p")
lines(conf.matches$id,conf.matches$Pa,col=4,pch=17,type="p")
legend("topleft",ncol=4,pch=c(1,15,16,17),col=c(1:4),
legend=c("OLS","OL (home)","OL (draw)","OL (away)"),bty="n")
abline(h=0.5,lty=2)
abline(h=0.6,lty=3)
abline(h=0.7,lty=2)
abline(h=0.4,lty=3)
for(i in 1:NROW(conf.matches)) {
if(conf.matches$outcome.final[i]==1) {
lines(conf.matches$id[i],conf.matches$outcome.final[i],col=2,type="p",pch=0)
lines(rep(i,2),c(conf.matches$Ph[i],conf.matches$outcome.final[i]),type="l",lty=2,col="red")
} else if (conf.matches$outcome.final[i]==0.5) {
lines(conf.matches$id[i],conf.matches$outcome.final[i],col=3,type="p",pch=1)
lines(rep(i,2),c(conf.matches$Pd[i],conf.matches$outcome.final[i]),type="l",lty=2,col="green")
} else {
lines(conf.matches$id[i],conf.matches$outcome.final[i],col=4,type="p",pch=2)
lines(rep(i,2),c(conf.matches$Pa[i],conf.matches$outcome.final[i]),type="l",lty=2,col="blue")
}
}
axis(1,at=conf.matches$id,labels=paste(conf.matches$team1,conf.matches$team2,sep=" v "),las=2,cex.axis=0.65)
Numerically it is important to evaluate forecast errors.
For the OLS model:
forecast.outcomes$error <- forecast.outcomes$outcome.final - forecast.outcomes$outcome.forc
forecast.outcomes$error2 <- forecast.outcomes$error^2
forecast.outcomes$aerror <- abs(forecast.outcomes$error)
#summary(forecast.outcomes[forecast.outcomes$tier<=5,c("error","error2","aerror")])
summary(forecast.outcomes[,c("error","error2","aerror")])
## error error2 aerror
## Min. :-0.761039 Min. :0.0000499 Min. :0.007061
## 1st Qu.:-0.491289 1st Qu.:0.0973211 1st Qu.:0.311958
## Median : 0.050055 Median :0.1935634 Median :0.439957
## Mean :-0.009673 Mean :0.1982307 Mean :0.410205
## 3rd Qu.: 0.383737 3rd Qu.:0.2795959 3rd Qu.:0.528767
## Max. : 0.645411 Max. :0.5791800 Max. :0.761039
For the ordered logit we must consider the three outcomes distinctly; for the home win:
forecast.outcomes$error.h <- forecast.outcomes$outcome.final - forecast.outcomes$Ph
forecast.outcomes$error.d <- as.numeric(forecast.outcomes$outcome.final==0.5) - forecast.outcomes$Pd
forecast.outcomes$error.a <- as.numeric(forecast.outcomes$outcome.final==0) - forecast.outcomes$Pa
forecast.outcomes$error.h2 <- forecast.outcomes$error.h^2
forecast.outcomes$error.d2 <- forecast.outcomes$error.d^2
forecast.outcomes$error.a2 <- forecast.outcomes$error.a^2
forecast.outcomes$aerror.h <- abs(forecast.outcomes$error.h)
forecast.outcomes$aerror.d <- abs(forecast.outcomes$error.d)
forecast.outcomes$aerror.a <- abs(forecast.outcomes$error.a)
#summary(forecast.outcomes[forecast.outcomes$tier<=5,c("error","error2","aerror")])
summary(forecast.outcomes[,c("error.h","error.d","error.a")])
## error.h error.d error.a
## Min. :-0.6717 Min. :-0.28092 Min. :-0.52094
## 1st Qu.:-0.3398 1st Qu.:-0.27787 1st Qu.:-0.29844
## Median : 0.1944 Median :-0.26218 Median :-0.20473
## Mean : 0.1240 Mean :-0.09792 Mean : 0.05577
## 3rd Qu.: 0.5200 3rd Qu.:-0.23416 3rd Qu.: 0.62020
## Max. : 0.7753 Max. : 0.79313 Max. : 0.86651
Considering here just the mean errors, the forecasts for home wins were biased downward much more than those for either the draw or away win; a positive forecast error suggests that the event occurs more often than the model predicts. Until we consider more forecasts, it is difficult to say whether this is simply an artifact of one particular week.
We can consider also, by division, forecast errors for our linear regression model:
library(knitr)
aggs <- aggregate(forecast.outcomes[,c("error","error2","aerror")],
by=list(forecast.outcomes$division),FUN=mean,na.rm=T)
kable(aggs[c(4,1,2,3,5),])
| Group.1 | error | error2 | aerror | |
|---|---|---|---|---|
| 4 | English League One | -0.1483071 | 0.2173745 | 0.4224580 |
| 1 | Capital One Cup | 0.3108814 | 0.0966472 | 0.3108814 |
| 2 | Conference North | 0.1177578 | 0.1347439 | 0.3476738 |
| 3 | English Championship | 0.0961382 | 0.2181794 | 0.4413849 |
| 5 | English League Two | -0.0501813 | 0.2018388 | 0.4054262 |
The error column is the mean forecast error, the error2 column is the mean squared forecast error, and the aerror column is the absolute forecast error.
We do the same for each outcome for the ordered probit model:
library(knitr)
aggs <- aggregate(forecast.outcomes[,c("error.h","error.h2","aerror.h")],
by=list(forecast.outcomes$division),FUN=mean,na.rm=T)
colnames(aggs) <- gsub("Group.1","Home win",colnames(aggs))
kable(aggs[c(4,1,2,3,5),])
| Home win | error.h | error.h2 | aerror.h | |
|---|---|---|---|---|
| 4 | English League One | -0.0154144 | 0.1954892 | 0.4023880 |
| 1 | Capital One Cup | 0.4208338 | 0.1771010 | 0.4208338 |
| 2 | Conference North | 0.2354484 | 0.1976760 | 0.3771473 |
| 3 | English Championship | 0.2296719 | 0.2623161 | 0.4774629 |
| 5 | English League Two | 0.0865886 | 0.2086549 | 0.4064594 |
aggs <- aggregate(forecast.outcomes[,c("error.d","error.d2","aerror.d")],
by=list(forecast.outcomes$division),FUN=mean,na.rm=T)
colnames(aggs) <- gsub("Group.1","Draw",colnames(aggs))
kable(aggs[c(4,1,2,3,5),])
| Draw | error.d | error.d2 | aerror.d | |
|---|---|---|---|---|
| 4 | English League One | -0.0536050 | 0.1675583 | 0.3606245 |
| 1 | Capital One Cup | -0.2345195 | 0.0549994 | 0.2345195 |
| 2 | Conference North | 0.2556535 | 0.3523031 | 0.5356719 |
| 3 | English Championship | -0.1764583 | 0.1090807 | 0.3005820 |
| 5 | English League Two | -0.0479502 | 0.1710035 | 0.3657584 |
aggs <- aggregate(forecast.outcomes[,c("error.a","error.a2","aerror.a")],
by=list(forecast.outcomes$division),FUN=mean,na.rm=T)
colnames(aggs) <- gsub("Group.1","Away win",colnames(aggs))
kable(aggs[c(4,1,2,3,5),])
| Away win | error.a | error.a2 | aerror.a | |
|---|---|---|---|---|
| 4 | English League One | 0.1731861 | 0.2839189 | 0.4802433 |
| 1 | Capital One Cup | -0.1863142 | 0.0347130 | 0.1863142 |
| 2 | Conference North | -0.2411019 | 0.0664978 | 0.2411019 |
| 3 | English Championship | -0.0115469 | 0.2087260 | 0.4091954 |
| 5 | English League Two | 0.0700573 | 0.2359236 | 0.4324683 |
Finally, we list all the forecasts again with outcomes:
kable(forecast.outcomes[order(forecast.outcomes$date,forecast.outcomes$division),
c("date","division","team1","goals1","goals2","team2",
"outcome.forc","Ph","Pd","Pa","outcome.final","error","error2","aerror")],digits=3)
| date | division | team1 | goals1 | goals2 | team2 | outcome.forc | Ph | Pd | Pa | outcome.final | error | error2 | aerror | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 103 | 2015-02-28 | Conference North | Bradford PA | 1 | 0 | Hednesford | 0.535 | 0.387 | 0.280 | 0.333 | 1.0 | 0.465 | 0.217 | 0.465 |
| 104 | 2015-02-28 | Conference North | Gainsborough | 3 | 3 | Hyde | 0.730 | 0.642 | 0.209 | 0.150 | 0.5 | -0.230 | 0.053 | 0.230 |
| 20 | 2015-02-28 | English Championship | Birmingham | 1 | 0 | Brentford | 0.483 | 0.333 | 0.280 | 0.387 | 1.0 | 0.517 | 0.267 | 0.517 |
| 23 | 2015-02-28 | English Championship | Leeds | 2 | 3 | Watford | 0.462 | 0.313 | 0.278 | 0.409 | 0.0 | -0.462 | 0.214 | 0.462 |
| 27 | 2015-02-28 | English Championship | Reading | 0 | 3 | Nottm Forest | 0.526 | 0.377 | 0.281 | 0.343 | 0.0 | -0.526 | 0.277 | 0.526 |
| 28 | 2015-02-28 | English Championship | Bolton | 1 | 0 | Brighton | 0.539 | 0.389 | 0.280 | 0.331 | 1.0 | 0.461 | 0.213 | 0.461 |
| 31 | 2015-02-28 | English Championship | Sheff Wed | 2 | 0 | Middlesbro | 0.417 | 0.266 | 0.269 | 0.465 | 1.0 | 0.583 | 0.340 | 0.583 |
| 32 | 2015-02-28 | English Championship | Charlton | 3 | 0 | Huddersfield | 0.579 | 0.438 | 0.274 | 0.288 | 1.0 | 0.421 | 0.178 | 0.421 |
| 36 | 2015-02-28 | English Championship | Bournemouth | 0 | 0 | Blackburn | 0.684 | 0.576 | 0.236 | 0.189 | 0.5 | -0.184 | 0.034 | 0.184 |
| 38 | 2015-02-28 | English Championship | Rotherham | 2 | 1 | Millwall | 0.603 | 0.465 | 0.269 | 0.266 | 1.0 | 0.397 | 0.158 | 0.397 |
| 39 | 2015-02-28 | English Championship | Cardiff | 0 | 1 | Wolves | 0.536 | 0.388 | 0.280 | 0.332 | 0.0 | -0.536 | 0.287 | 0.536 |
| 41 | 2015-02-28 | English Championship | Fulham | 2 | 0 | Derby | 0.355 | 0.225 | 0.254 | 0.521 | 1.0 | 0.645 | 0.417 | 0.645 |
| 42 | 2015-02-28 | English Championship | Blackpool | 1 | 3 | Wigan | 0.523 | 0.372 | 0.281 | 0.347 | 0.0 | -0.523 | 0.273 | 0.523 |
| 43 | 2015-02-28 | English League One | Gillingham | 0 | 1 | Barnsley | 0.629 | 0.499 | 0.261 | 0.241 | 0.0 | -0.629 | 0.396 | 0.629 |
| 45 | 2015-02-28 | English League One | Walsall | 0 | 2 | Leyton Orient | 0.634 | 0.500 | 0.260 | 0.240 | 0.0 | -0.634 | 0.402 | 0.634 |
| 47 | 2015-02-28 | English League One | Peterborough | 2 | 0 | Bradford | 0.529 | 0.381 | 0.280 | 0.339 | 1.0 | 0.471 | 0.222 | 0.471 |
| 52 | 2015-02-28 | English League One | Crewe | 0 | 0 | Swindon | 0.423 | 0.281 | 0.273 | 0.446 | 0.5 | 0.077 | 0.006 | 0.077 |
| 55 | 2015-02-28 | English League One | Bristol C | 1 | 0 | Rochdale | 0.652 | 0.527 | 0.253 | 0.221 | 1.0 | 0.348 | 0.121 | 0.348 |
| 56 | 2015-02-28 | English League One | Chesterfield | 3 | 0 | Fleetwood | 0.564 | 0.421 | 0.277 | 0.302 | 1.0 | 0.436 | 0.190 | 0.436 |
| 57 | 2015-02-28 | English League One | Doncaster | 2 | 0 | Colchester | 0.655 | 0.529 | 0.252 | 0.219 | 1.0 | 0.345 | 0.119 | 0.345 |
| 59 | 2015-02-28 | English League One | Oldham | 0 | 4 | Preston | 0.493 | 0.341 | 0.281 | 0.379 | 0.0 | -0.493 | 0.243 | 0.493 |
| 61 | 2015-02-28 | English League One | Crawley | 1 | 1 | Sheff Utd | 0.477 | 0.330 | 0.280 | 0.390 | 0.5 | 0.023 | 0.001 | 0.023 |
| 64 | 2015-02-28 | English League One | Scunthorpe | 1 | 1 | Yeovil | 0.665 | 0.544 | 0.247 | 0.209 | 0.5 | -0.165 | 0.027 | 0.165 |
| 65 | 2015-02-28 | English League One | Coventry | 2 | 1 | MK Dons | 0.402 | 0.263 | 0.268 | 0.469 | 1.0 | 0.598 | 0.357 | 0.598 |
| 66 | 2015-02-28 | English League One | Notts Co | 0 | 1 | Port Vale | 0.558 | 0.413 | 0.278 | 0.309 | 0.0 | -0.558 | 0.311 | 0.558 |
| 68 | 2015-02-28 | English League Two | Cheltenham | 2 | 0 | Tranmere | 0.515 | 0.363 | 0.281 | 0.356 | 1.0 | 0.485 | 0.235 | 0.485 |
| 71 | 2015-02-28 | English League Two | Morecambe | 0 | 2 | Cambridge U | 0.610 | 0.472 | 0.267 | 0.261 | 0.0 | -0.610 | 0.372 | 0.610 |
| 72 | 2015-02-28 | English League Two | Southend | 2 | 0 | Carlisle | 0.693 | 0.575 | 0.236 | 0.189 | 1.0 | 0.307 | 0.094 | 0.307 |
| 75 | 2015-02-28 | English League Two | Portsmouth | 0 | 0 | Oxford | 0.633 | 0.501 | 0.260 | 0.239 | 0.5 | -0.133 | 0.018 | 0.133 |
| 76 | 2015-02-28 | English League Two | Plymouth | 0 | 2 | Bury | 0.631 | 0.499 | 0.261 | 0.240 | 0.0 | -0.631 | 0.398 | 0.631 |
| 77 | 2015-02-28 | English League Two | Hartlepool | 1 | 0 | AFC W’bledon | 0.470 | 0.322 | 0.279 | 0.399 | 1.0 | 0.530 | 0.280 | 0.530 |
| 79 | 2015-02-28 | English League Two | Mansfield | 2 | 1 | Dag & Red | 0.559 | 0.411 | 0.278 | 0.311 | 1.0 | 0.441 | 0.194 | 0.441 |
| 81 | 2015-02-28 | English League Two | Shrewsbury | 1 | 2 | Northampton | 0.648 | 0.518 | 0.255 | 0.227 | 0.0 | -0.648 | 0.419 | 0.648 |
| 83 | 2015-02-28 | English League Two | Luton | 2 | 0 | Accrington | 0.670 | 0.549 | 0.245 | 0.205 | 1.0 | 0.330 | 0.109 | 0.330 |
| 84 | 2015-02-28 | English League Two | Wycombe | 2 | 2 | Stevenage | 0.638 | 0.507 | 0.258 | 0.234 | 0.5 | -0.138 | 0.019 | 0.138 |
| 85 | 2015-02-28 | English League Two | Burton | 0 | 1 | Newport Co | 0.684 | 0.564 | 0.240 | 0.196 | 0.0 | -0.684 | 0.468 | 0.684 |
| 86 | 2015-02-28 | English League Two | York | 0 | 0 | Exeter | 0.581 | 0.441 | 0.274 | 0.285 | 0.5 | -0.081 | 0.007 | 0.081 |
| 1 | 2015-02-28 | English Premier | Man Utd | 2 | 0 | Sunderland | 0.675 | 0.564 | 0.240 | 0.196 | 1.0 | 0.325 | 0.106 | 0.325 |
| 3 | 2015-02-28 | English Premier | Stoke | 1 | 0 | Hull | 0.615 | 0.479 | 0.266 | 0.255 | 1.0 | 0.385 | 0.148 | 0.385 |
| 5 | 2015-02-28 | English Premier | Newcastle | 1 | 0 | Aston Villa | 0.658 | 0.533 | 0.251 | 0.216 | 1.0 | 0.342 | 0.117 | 0.342 |
| 6 | 2015-02-28 | English Premier | Burnley | 0 | 1 | Swansea | 0.517 | 0.369 | 0.281 | 0.351 | 0.0 | -0.517 | 0.267 | 0.517 |
| 7 | 2015-02-28 | English Premier | West Ham | 1 | 3 | C Palace | 0.625 | 0.496 | 0.262 | 0.243 | 0.0 | -0.625 | 0.390 | 0.625 |
| 8 | 2015-02-28 | English Premier | West Brom | 1 | 0 | Southampton | 0.451 | 0.300 | 0.276 | 0.424 | 1.0 | 0.549 | 0.302 | 0.549 |
| 110 | 2015-02-28 | FA Trophy | Torquay | 0 | 3 | Wrexham | 0.624 | 0.494 | 0.262 | 0.244 | 0.0 | -0.624 | 0.389 | 0.624 |
| 90 | 2015-02-28 | Football Conference | Kidderminster | 0 | 0 | Halifax | 0.521 | 0.370 | 0.281 | 0.349 | 0.5 | -0.021 | 0.000 | 0.021 |
| 91 | 2015-02-28 | Football Conference | Forest Green | 5 | 3 | Southport | 0.731 | 0.632 | 0.213 | 0.155 | 1.0 | 0.269 | 0.072 | 0.269 |
| 92 | 2015-02-28 | Football Conference | Eastleigh | 4 | 0 | Macclesfield | 0.561 | 0.419 | 0.277 | 0.304 | 1.0 | 0.439 | 0.193 | 0.439 |
| 93 | 2015-02-28 | Football Conference | Grimsby | 1 | 0 | Braintree | 0.696 | 0.580 | 0.234 | 0.186 | 1.0 | 0.304 | 0.092 | 0.304 |
| 95 | 2015-02-28 | Football Conference | Gateshead | 0 | 1 | Bristol R | 0.557 | 0.412 | 0.278 | 0.310 | 0.0 | -0.557 | 0.310 | 0.557 |
| 96 | 2015-02-28 | Football Conference | Telford | 0 | 1 | Alfreton | 0.599 | 0.468 | 0.268 | 0.264 | 0.0 | -0.599 | 0.359 | 0.599 |
| 99 | 2015-02-28 | Football Conference | Nuneaton | 1 | 0 | Welling | 0.536 | 0.389 | 0.280 | 0.331 | 1.0 | 0.464 | 0.215 | 0.464 |
| 100 | 2015-02-28 | Football Conference | Lincoln | 0 | 2 | Woking | 0.527 | 0.377 | 0.281 | 0.342 | 0.0 | -0.527 | 0.277 | 0.527 |
| 101 | 2015-02-28 | Football Conference | Altrincham | 1 | 3 | Barnet | 0.437 | 0.295 | 0.275 | 0.430 | 0.0 | -0.437 | 0.191 | 0.437 |
| 102 | 2015-02-28 | Football Conference | Aldershot | 1 | 1 | Dartford | 0.644 | 0.516 | 0.256 | 0.228 | 0.5 | -0.144 | 0.021 | 0.144 |
| 105 | 2015-02-28 | Ryman Premier | Canvey Isl. | 1 | 1 | Lewes | 0.737 | 0.646 | 0.207 | 0.147 | 0.5 | -0.237 | 0.056 | 0.237 |
| 106 | 2015-02-28 | Ryman Premier | Kingstonian | 3 | 3 | Margate | 0.507 | 0.359 | 0.281 | 0.360 | 0.5 | -0.007 | 0.000 | 0.007 |
| 109 | 2015-03-01 | Capital One Cup | Chelsea | 2 | 0 | Tottenham | 0.689 | 0.579 | 0.235 | 0.186 | 1.0 | 0.311 | 0.097 | 0.311 |
| 40 | 2015-03-01 | English Championship | Norwich | 2 | 0 | Ipswich | 0.635 | 0.509 | 0.258 | 0.233 | 1.0 | 0.365 | 0.133 | 0.365 |
| 2 | 2015-03-01 | English Premier | Arsenal | 2 | 0 | Everton | 0.689 | 0.577 | 0.235 | 0.188 | 1.0 | 0.311 | 0.097 | 0.311 |
| 4 | 2015-03-01 | English Premier | Liverpool | 2 | 1 | Man City | 0.553 | 0.409 | 0.278 | 0.313 | 1.0 | 0.447 | 0.200 | 0.447 |
| 19 | 2015-03-03 | English Championship | Brighton | 2 | 0 | Derby | 0.431 | 0.286 | 0.274 | 0.441 | 1.0 | 0.569 | 0.323 | 0.569 |
| 22 | 2015-03-03 | English Championship | Watford | 1 | 0 | Fulham | 0.757 | 0.666 | 0.198 | 0.137 | 1.0 | 0.243 | 0.059 | 0.243 |
| 26 | 2015-03-03 | English Championship | Bolton | 1 | 1 | Reading | 0.575 | 0.435 | 0.275 | 0.291 | 0.5 | -0.075 | 0.006 | 0.075 |
| 29 | 2015-03-03 | English Championship | Bournemouth | 2 | 1 | Wolves | 0.652 | 0.536 | 0.250 | 0.215 | 1.0 | 0.348 | 0.121 | 0.348 |
| 30 | 2015-03-03 | English Championship | Middlesbro | 3 | 0 | Millwall | 0.777 | 0.687 | 0.187 | 0.125 | 1.0 | 0.223 | 0.050 | 0.223 |
| 34 | 2015-03-03 | English Championship | Rotherham | 1 | 3 | Cardiff | 0.526 | 0.377 | 0.281 | 0.343 | 0.0 | -0.526 | 0.277 | 0.526 |
| 35 | 2015-03-03 | English Championship | Charlton | 2 | 1 | Nottm Forest | 0.521 | 0.372 | 0.281 | 0.347 | 1.0 | 0.479 | 0.229 | 0.479 |
| 37 | 2015-03-03 | English Championship | Brentford | 4 | 1 | Huddersfield | 0.655 | 0.531 | 0.251 | 0.218 | 1.0 | 0.345 | 0.119 | 0.345 |
| 44 | 2015-03-03 | English League One | Swindon | 0 | 3 | Gillingham | 0.656 | 0.538 | 0.249 | 0.213 | 0.0 | -0.656 | 0.430 | 0.656 |
| 46 | 2015-03-03 | English League One | Bradford | 1 | 0 | Crawley | 0.703 | 0.593 | 0.229 | 0.178 | 1.0 | 0.297 | 0.088 | 0.297 |
| 48 | 2015-03-03 | English League One | Rochdale | 4 | 0 | Crewe | 0.685 | 0.581 | 0.234 | 0.185 | 1.0 | 0.315 | 0.099 | 0.315 |
| 49 | 2015-03-03 | English League One | Colchester | 0 | 1 | Notts Co | 0.583 | 0.441 | 0.273 | 0.285 | 0.0 | -0.583 | 0.340 | 0.583 |
| 50 | 2015-03-03 | English League One | Leyton Orient | 1 | 3 | Bristol C | 0.444 | 0.300 | 0.276 | 0.423 | 0.0 | -0.444 | 0.197 | 0.444 |
| 51 | 2015-03-03 | English League One | Port Vale | 0 | 1 | Oldham | 0.575 | 0.434 | 0.275 | 0.291 | 0.0 | -0.575 | 0.331 | 0.575 |
| 53 | 2015-03-03 | English League One | Preston | 2 | 2 | Doncaster | 0.665 | 0.543 | 0.247 | 0.210 | 0.5 | -0.165 | 0.027 | 0.165 |
| 54 | 2015-03-03 | English League One | Sheff Utd | 1 | 2 | Peterborough | 0.661 | 0.538 | 0.249 | 0.213 | 0.0 | -0.661 | 0.437 | 0.661 |
| 58 | 2015-03-03 | English League One | Barnsley | 1 | 0 | Coventry | 0.619 | 0.484 | 0.265 | 0.252 | 1.0 | 0.381 | 0.145 | 0.381 |
| 60 | 2015-03-03 | English League One | MK Dons | 1 | 2 | Chesterfield | 0.691 | 0.586 | 0.232 | 0.182 | 0.0 | -0.691 | 0.477 | 0.691 |
| 62 | 2015-03-03 | English League One | Yeovil | 0 | 1 | Walsall | 0.489 | 0.336 | 0.280 | 0.384 | 0.0 | -0.489 | 0.239 | 0.489 |
| 63 | 2015-03-03 | English League One | Fleetwood | 2 | 2 | Scunthorpe | 0.606 | 0.466 | 0.269 | 0.265 | 0.5 | -0.106 | 0.011 | 0.106 |
| 67 | 2015-03-03 | English League Two | Carlisle | 1 | 0 | Cheltenham | 0.625 | 0.493 | 0.262 | 0.245 | 1.0 | 0.375 | 0.141 | 0.375 |
| 69 | 2015-03-03 | English League Two | Northampton | 1 | 0 | Portsmouth | 0.605 | 0.470 | 0.268 | 0.262 | 1.0 | 0.395 | 0.156 | 0.395 |
| 70 | 2015-03-03 | English League Two | Stevenage | 1 | 0 | Plymouth | 0.526 | 0.374 | 0.281 | 0.345 | 1.0 | 0.474 | 0.225 | 0.474 |
| 73 | 2015-03-03 | English League Two | Tranmere | 1 | 2 | Wycombe | 0.482 | 0.333 | 0.280 | 0.387 | 0.0 | -0.482 | 0.232 | 0.482 |
| 74 | 2015-03-03 | English League Two | AFC W’bledon | 0 | 0 | Southend | 0.566 | 0.423 | 0.276 | 0.301 | 0.5 | -0.066 | 0.004 | 0.066 |
| 78 | 2015-03-03 | English League Two | Cambridge U | 0 | 3 | York | 0.611 | 0.477 | 0.266 | 0.257 | 0.0 | -0.611 | 0.374 | 0.611 |
| 80 | 2015-03-03 | English League Two | Newport Co | 0 | 1 | Mansfield | 0.629 | 0.496 | 0.261 | 0.243 | 0.0 | -0.629 | 0.395 | 0.629 |
| 82 | 2015-03-03 | English League Two | Oxford | 1 | 1 | Morecambe | 0.565 | 0.420 | 0.277 | 0.303 | 0.5 | -0.065 | 0.004 | 0.065 |
| 87 | 2015-03-03 | English League Two | Accrington | 1 | 2 | Shrewsbury | 0.461 | 0.311 | 0.278 | 0.411 | 0.0 | -0.461 | 0.212 | 0.461 |
| 88 | 2015-03-03 | English League Two | Bury | 1 | 0 | Luton | 0.582 | 0.439 | 0.274 | 0.287 | 1.0 | 0.418 | 0.175 | 0.418 |
| 89 | 2015-03-03 | English League Two | Dag & Red | 2 | 0 | Hartlepool | 0.670 | 0.551 | 0.245 | 0.204 | 1.0 | 0.330 | 0.109 | 0.330 |
| 10 | 2015-03-03 | English Premier | Hull | 1 | 1 | Sunderland | 0.598 | 0.459 | 0.270 | 0.270 | 0.5 | -0.098 | 0.010 | 0.098 |
| 11 | 2015-03-03 | English Premier | Aston Villa | 2 | 1 | West Brom | 0.502 | 0.349 | 0.281 | 0.371 | 1.0 | 0.498 | 0.248 | 0.498 |
| 12 | 2015-03-03 | English Premier | Southampton | 1 | 0 | C Palace | 0.683 | 0.568 | 0.239 | 0.193 | 1.0 | 0.317 | 0.100 | 0.317 |
| 94 | 2015-03-03 | Football Conference | Dartford | 1 | 3 | Woking | 0.435 | 0.289 | 0.274 | 0.437 | 0.0 | -0.435 | 0.189 | 0.435 |
| 97 | 2015-03-03 | Football Conference | Aldershot | 3 | 1 | Dover | 0.501 | 0.350 | 0.281 | 0.370 | 1.0 | 0.499 | 0.249 | 0.499 |
| 98 | 2015-03-03 | Football Conference | Braintree | 0 | 1 | Macclesfield | 0.492 | 0.342 | 0.281 | 0.378 | 0.0 | -0.492 | 0.242 | 0.492 |
| 107 | 2015-03-03 | Football Conference | Gateshead | 3 | 1 | Wrexham | 0.656 | 0.531 | 0.251 | 0.218 | 1.0 | 0.344 | 0.119 | 0.344 |
| 108 | 2015-03-03 | Football Conference | Southport | 1 | 0 | Halifax | 0.423 | 0.277 | 0.272 | 0.451 | 1.0 | 0.577 | 0.332 | 0.577 |
| 21 | 2015-03-04 | English Championship | Leeds | 2 | 1 | Ipswich | 0.481 | 0.331 | 0.280 | 0.390 | 1.0 | 0.519 | 0.269 | 0.519 |
| 24 | 2015-03-04 | English Championship | Sheff Wed | 1 | 2 | Blackburn | 0.550 | 0.400 | 0.279 | 0.321 | 0.0 | -0.550 | 0.302 | 0.550 |
| 25 | 2015-03-04 | English Championship | Birmingham | 1 | 0 | Blackpool | 0.665 | 0.547 | 0.246 | 0.207 | 1.0 | 0.335 | 0.112 | 0.335 |
| 33 | 2015-03-04 | English Championship | Norwich | 0 | 1 | Wigan | 0.761 | 0.672 | 0.195 | 0.133 | 0.0 | -0.761 | 0.579 | 0.761 |
| 9 | 2015-03-04 | English Premier | West Ham | 0 | 1 | Chelsea | 0.443 | 0.293 | 0.275 | 0.431 | 0.0 | -0.443 | 0.196 | 0.443 |
| 13 | 2015-03-04 | English Premier | QPR | 1 | 2 | Arsenal | 0.389 | 0.248 | 0.263 | 0.488 | 0.0 | -0.389 | 0.151 | 0.389 |
| 14 | 2015-03-04 | English Premier | Liverpool | 2 | 0 | Burnley | 0.710 | 0.603 | 0.225 | 0.172 | 1.0 | 0.290 | 0.084 | 0.290 |
| 15 | 2015-03-04 | English Premier | Stoke | 2 | 0 | Everton | 0.588 | 0.446 | 0.273 | 0.281 | 1.0 | 0.412 | 0.170 | 0.412 |
| 16 | 2015-03-04 | English Premier | Tottenham | 3 | 2 | Swansea | 0.629 | 0.498 | 0.261 | 0.241 | 1.0 | 0.371 | 0.138 | 0.371 |
| 17 | 2015-03-04 | English Premier | Man City | 2 | 0 | Leicester | 0.715 | 0.622 | 0.217 | 0.161 | 1.0 | 0.285 | 0.081 | 0.285 |
| 18 | 2015-03-04 | English Premier | Newcastle | 0 | 1 | Man Utd | 0.482 | 0.332 | 0.280 | 0.388 | 0.0 | -0.482 | 0.232 | 0.482 |