Squad Rotation StudyΒΆ

Squad rotation is a fact of life for professional soccer team managers as they attempt to manage resources over multiple competitions at the same time. In this example we use the Soccermetrics API to access starting lineups for a team in all of their league matches, and then compare the week-by-week changes in the starting eleven.

Language

This script is written in Python 2.7 using the official API client for Python. The client simplifies the process of making HTTP requests to the Soccermetrics API and unpacking the responses.

The total length of the script is about 30 lines. If you want to display the data graphically, count on an extra 20-30 lines of Python code.

Concept

This script calls match.information.get() and match.link.get(), making use of the hypertext provided with the match.information response.

Walkthrough

At the very top of the script we import the SoccermetricsRestClient package that will allow us to communicate with the API.

from soccermetrics.rest import SoccermetricsRestClient

In the main routine we create a SoccermetricsRestClient object. You can instantiate it by passing the authentication tokens through the account and api_key variables, but we recommend storing those tokens in environmental variables.

if __name__ == "__main__":
    client = SoccermetricsRestClient()

We create a STARTING_XI constant and set it to 11. (There’s a Spinal Tap joke in there somewhere.) It’s not necessary to create this, but we believe very strongly in not hard-coding numbers in our code.

STARTING_XI = 11

We also create a club_name variable and set it to “Liverpool”. Again, it’s not necessary, but it gets us away from hard-coding and enables reuse.

club_name = "Liverpool"

Then, we retrieve match information data from all of Liverpool’s matches. We do this by first querying for all of Liverpool’s home matches, then all of their away matches. Response data from the API are split into pages, but we can get the full dataset at once with the all() method.

Results from the API are unsorted, so we sort the results by match date. (You can also sort by matchday but not all matches are played in order.)

Note

Data payloads from the API are accessed using dot notation, in the same manner that JSON objects are accessed in Javascript.

matches = []
for key in ['home_team_name','away_team_name']:
    param = {key: club_name}
    matches.extend(client.match.information.get(**param).all())
sorted_matches = sorted(matches, key=lambda k: k.match_date)

Now we reach is the main loop where everything happens. We loop over the list of sorted matches (and make sure you’re using the right variable!) and grab starting lineup data from Liverpool’s matches. We could use match.lineups.get() but it’s much easier to use the lineups hyperlink in the match information response. We use client.link.get() to access the lineups resource.

We are interested in the starting players for Liverpool so we make player_team equal to “Liverpool” and is_starting to True. We grab the IDs of the players in the lineup and store those in a list, and store that list in another list.

After we’ve gone through the loop once, we can calculate squad rotations. And it’s simple using Python’s set functionality – compute the number of players who are in the current lineup and the previous one. Subtract that number from STARTING_XI to get the number of rotated players.

starters = []
rotation_list = []
for match in sorted_matches:

    lineup_data = client.link.get(match.link.lineups,player_team_name=club_name,
        is_starting=True).all()
    player_list = [x.player for x in lineup_data]
    starters.append(player_list)

    if len(starters) > 1:
        num_no_changes = len(set(starters[-2]).intersection(starters[-1]))
        rotation_list.append(dict(date=match.match_date,
            matchday=match.matchday, rotations=STARTING_XI-num_no_changes))

Finally we display the results on screen – matchday, match date, rotations, and cumulative rotations. There are lots of ways to make the data prettier, and we leave that as an exercise for you!

print "Match\tMatch Date\tRotations\tTotal Rotations"
cumul = []
for datum in rotation_list:
    cumul.append(datum['rotations'])
    print "%d\t%s\t%d\t%d" % (datum['matchday'],datum['date'],datum.['rotations'],
                              sum(cumul))

Here are the results:

Match   Match Date  Rotations   Total Rotations
2       2011-08-20  2           2
3       2011-08-27  1           3
4       2011-09-10  1           4
5       2011-09-18  1           5
6       2011-09-24  1           6
7       2011-10-01  1           7
8       2011-10-15  1           8
9       2011-10-22  2           10
10      2011-10-29  4           14
11      2011-11-05  0           14
12      2011-11-20  3           17
13      2011-11-27  2           19
14      2011-12-05  3           22
15      2011-12-10  3           25
16      2011-12-18  2           27
17      2011-12-21  2           29
18      2011-12-26  1           30
19      2011-12-30  2           32
20      2012-01-03  1           33
21      2012-01-14  3           36
22      2012-01-21  4           40
23      2012-01-31  2           42
24      2012-02-06  2           44
25      2012-02-11  4           48
27      2012-03-03  3           51
28      2012-03-10  2           53
26      2012-03-13  4           57
29      2012-03-21  2           59
30      2012-03-24  2           61
31      2012-04-01  3           64
32      2012-04-07  4           68
33      2012-04-10  6           74
35      2012-04-22  5           79
36      2012-04-28  5           84
34      2012-05-01  9           93
37      2012-05-08  6           99
38      2012-05-13  2           101

Full Script

#!/usr/bin/env python

from soccermetrics.rest import SoccermetricsRestClient

if __name__ == "__main__":
    client = SoccermetricsRestClient()

    STARTING_XI = 11

    matches = []
    for key in ['home_team_name','away_team_name']:
        param = {key: club_name}
        matches.extend(client.match.information.get(**param).all())
    sorted_matches = sorted(matches, key=lambda k: k.match_date)

    starters = []
    rotation_list = []
    for match in sorted_matches:

        lineup_data = client.link.get(match.link.lineups,player_team_name=club_name,
            is_starting=True).all()
        player_list = [x.player for x in lineup_data]
        starters.append(player_list)

        if len(starters) > 1:
            num_no_changes = len(set(starters[-2]).intersection(starters[-1]))
            rotation_list.append(dict(date=match.match_date,
                matchday=match.matchday, rotations=STARTING_XI-num_no_changes))

    print "Match\tMatch Date\tRotations\tTotal Rotations"
    cumul = []
    for datum in rotation_list:
        cumul.append(datum['rotations'])
        print "%d\t%s\t%d\t%d" % (datum['matchday'],datum['date'],datum['rotations'],sum(cumul))