EPL 21-23 November 2015
EPL November 21st - 23rd 2015
Another brief look at some of the simple statistics underlying the weekend games in the English Premier League.
%matplotlib inline
import league_analysis
from IPython.display import display, HTML
epl = league_analysis.epl
weekend_matches = league_analysis.get_matches(epl, '21/11/2015', '23/11/2015')
league_analysis.display_given_matches(weekend_matches)
league_analysis.display_match(epl, 'Chelsea', 'Norwich', '21/11/15')
Similar to their win against Aston Villa before a poor run of results, Chelsea really needed a win here. It looks as though their 1-0 victory was if anything a little unflattering. Such a performance will be encouraging, though it is still beating teams around the relegation battle rather than those they might hope to surpass into one of the four champions' league spots.
epl.compare_game_against_opponents('Chelsea', 'Norwich', '21/11/15')
So, Chelsea with 21 shots took 6 and a half shots more than usual and 7 more than the average team does against Norwich. They also only allowed 4 shots, whereas Norwich normally take nearly 13 and Chelsea normally allow over 12. Similar statistics for the shots on target. Overall then a pretty good display from the champions, even if the narrow scoreline probably had a few Chelsea fans worried about a late equaliser.
league_analysis.display_match(epl, 'Everton', 'Aston Villa', '21/11/15')
Probably the most predictable of the results this weekend (with Tottenham's win over West Ham a good second). The scoreline looks a little harsh on Aston Villa. Worrying signs for Aston Villa, now bottom in the league for goals scored and goal difference, and not doing great on the goals conceded front either.
pairs = [(stats.teamname, stats.goals_for - stats.goals_against)
for stats in epl.team_stats.values()]
league_analysis.display_ranked_table(['Team', 'Goal Difference'], pairs)
pairs = [(stats.teamname, stats.goals_for)
for stats in epl.team_stats.values()]
league_analysis.display_ranked_table(['Team', 'Goals For'], pairs)
pairs = [(stats.teamname, stats.goals_against)
for stats in epl.team_stats.values()]
league_analysis.display_ranked_table(['Team', 'Goals Against'], pairs, reverse=False)
league_analysis.display_match(epl, 'Man City', 'Liverpool', '21/11/15')
Concerning the last table this game is the reason that Manchester City were not joint top with Manchester United for goals conceded. It's hard to argue with the score line as well, with 9 shots on target Liverpool were significantly better than most teams have managed against Manchester City:
epl.compare_game_against_opponents('Man City', 'Liverpool', '21/11/15')
Restricting the home side to just 11 shots from an average of more than 17 is impressive, and done when taking 14 shots themselves. Basically Liverpool have managed to restrict Manchester City to looking like an average team that plays Liverpool (that average team usually manage 10.8 shots and 3.2 shots on target), but have done so whilst looking anything like an average team that takes on Manchester City. Even Tottenham, the other team to have beaten Man City 4-1, did not manage to out-shoot them, and were pretty fortunate to win 4-1:
league_analysis.display_given_matches(league_analysis.get_matches_between([epl], 'Man City', 'Tottenham'))
league_analysis.display_match(epl, 'Newcastle', 'Leicester', '21/11/15')
And so to the new league leaders. Say what you want you about Leicester and how they might not sustain this run, but they certainly deserved their victory here. In fact the interest around Leicester's rise to the top of the table should not distract us from the danger that Newcastle find themselves. This is pretty terrible stuff, losing at home so comprehsively.
league_analysis.display_match(epl, 'Southampton', 'Stoke', '21/11/15')
This was pretty surprising, Stoke have not had great numbers so far this season. Although with the influx of some talent it was a bit of a surprise that Stoke's numbers were quite as bad as they were and perhaps many expected an up-tick. Still, an excellent away victory at Southampton, all the more for having competed so well on the shot counts. This was not like the defeat of Chelsea in which they suffered something of a battering. This was a solid display (at least in terms of shot numbers).
league_analysis.display_match(epl, 'Swansea', 'Bournemouth', '21/11/15')
Bournemouth just cannot catch a break. Though to be fair Bournemouth had a two goal lead here and probably should have held on, but an away draw is not a disaster. Still, their PDO has not been their friend, I fully expect Bournemouth to remain in the division:
pairs = [(stats.teamname, stats.pdo)
for stats in epl.team_stats.values()]
league_analysis.display_ranked_table(['Team', 'PDO'], pairs)
Just look at that number. They are minus 0.23 more than double the negative of the next worse off team Liverpool. Also worth noting here is that Leicester aren't getting an incredible amount of luck.
league_analysis.display_match(epl, 'Watford', 'Man United', '21/11/15')
The above table showed the league leaders in PDO are Manchester United. However, we know that PDO is an imperfect measure of luck, and that Mancester United do seem to have some qualities that allow them to defy measure. A good article at statsbomb (by Marek Kwiatkowski otherwise known as statlurker), is a nice discussion of one way in which shot statistics might miss "near chances". So perhaps Manchester United create a lot of plays that do not result in shots but nearly a shot from a highly dangerous position. In other words a cross/pass which missed its target but had it done so would have resulted in a goal with high probability. Having watched Manchester United play this season I'm a little sceptical of that explanation (for this season).
Still, this was a game that Mancester United probably deserved to win, but it highlights a problem with playing in such a closed manner. You're susceptible to the vagries of chance. In other words, you're more likely to lose if you out-shoot your opponents 5-3 than you are if you out-shoot them 20-12. Since Man United should probably consider themselves favourites for most games against league opponents this season, their tactics are at least a bit questionable. But that is a topic that deserves much more than a brief look.
Of course I say all this despite the fact that actually Watford have managed quite a decent number of shots and shots on target against the generally miserly Man United. Watford are in danger of coming off as plucky-losers a lot, but the general signs points to a pretty decent team that should manage to remain in the league, they certainly seem better than Newcastle, Sunderland and Aston Villa.
league_analysis.display_match(epl, 'West Brom', 'Arsenal', '21/11/15')
Great win for West Brom. Another defeat for Arsenal despite dominating the game for large portions. Still, Arsenal are clearly title contenders this season.
league_analysis.display_match(epl, 'Tottenham', 'West Ham', '22/11/15')
This was pretty predictable. Tottenham are beginning to look better and better this season. With the very lacklustre start to the campaign for the champions, a top 4 spot has looked well within Tottenham's grasp. Having seen Arsenal and City lose this weekend I suspect Spurs fans are starting to dream of a title-bid if not exactly a title. Probably a little premature for that, but still, it's been a long time since Spurs lost a league match.
I don't wish to harp on at West Ham, but they are still over-performing. I still think they will not manage to remain in the top half of the table.
league_analysis.display_match(epl, 'Crystal Palace', 'Sunderland', '23/11/15')
File this one under, "Did not see that coming". However, once again the shots statistics show that Sunderland probably did not deserve this win. I say once again, because Sunderland have only won two games this season, and both have been seemingly undeserved:
def filter_fun(match):
return ((match.HomeTeam == 'Sunderland' and match.FTR == 'H') or
(match.AwayTeam == 'Sunderland' and match.FTR == 'A'))
relevant_matches = league_analysis.get_all_matches(years=[league_analysis.year_201516], filter_fun=filter_fun)
league_analysis.display_given_matches(relevant_matches)
Worrying times, unless you're a Newcastle fan, except that:
def filter_fun(match):
return ((match.HomeTeam == 'Newcastle' and match.FTR == 'H') or
(match.AwayTeam == 'Newcastle' and match.FTR == 'A'))
relevant_matches = league_analysis.get_all_matches(years=[league_analysis.year_201516], filter_fun=filter_fun)
league_analysis.display_given_matches(relevant_matches)
Still it could be worse, you could have only won one game, which you probably didn't deserve:
def filter_fun(match):
return ((match.HomeTeam == 'Aston Villa' and match.FTR == 'H') or
(match.AwayTeam == 'Aston Villa' and match.FTR == 'A'))
relevant_matches = league_analysis.get_all_matches(years=[league_analysis.year_201516], filter_fun=filter_fun)
league_analysis.display_given_matches(relevant_matches)
As I said, poor old Bournemouth.
Thanks for reading.
Comments
Comments powered by Disqus