How All-Rounder Ratings are Calculated in Cricket

The rise of Ben Stokes.

Neeraj Shah
Towards Data Science

--

If you have been following cricket at all in the last year, you will have heard of Ben Stokes. He has been a match winner for England and had the comeback story of a life-time.

NAPARAZZI / CC BY-SA (https://creativecommons.org/licenses/by-sa/2.0)

Now, he is statistically the world’s best test all-rounder, having recently overtaken the captain of the West Indies, Jason Holder.

I want to better understand what that title means.

Today, I will use web scraping and basic machine learning in python to uncover some findings of how all-rounders are rated in test cricket. Although many of my conclusions are already outlined in ranking overviews, the setup and approach I use can be applied to more complex problems.

Background

This piece is not intended to teach cricket. While I will provide a basic overview of Test cricket, I would recommend checking out these videos if you would like to learn more.

Photo by Chirayu Trivedi on Unsplash

In a Test cricket match, each team gets to participate in batting and bowling. Batsmen try to score “runs”, and bowlers try to limit these runs. To win a match, a team must score more runs than their opponent.

Typically, teams have some players who are “specialist bowlers” and some players who are “specialist batsmen”. Specialist players have one main responsibility — batting or bowling.

There are also all-rounders like Ben Stokes. These are players who are good enough at batting and bowling to be selected to do both.

The International Cricket Council (ICC) has a somewhat opaque way of calculating a players batting or bowling rating. There are many considerations that they incorporate into how a player’s batting or bowling rating changes after a game, including the quality of the other team’s players, the performance of other players on the same team, and whether the player’s team wins or not.

Batting and bowling ratings are designed to be entirely derivable from match statistics alone — there is no panel of judges that decides how a player’s rating changes.

Likewise, all-rounder ratings are supposed to be entirely derivable from batting and bowling ratings. To find the exact relationship between batting, bowling, and all-rounder ratings, I looked to data.

Scraping the Data

I started off by gathering ICC-maintained test cricket ratings of players. The Python scraping library I used is called BeautifulSoup. I chose it because it handles custom scraping solutions without requiring me to use a specific post-processing solution. BeautifulSoup also only handles HTML strings as inputs, so I have to use a tool like requests to retrieve the URL in question first. An example is shown below:

Setting up for scraping

I knew that scraping would be doable after I saw the form of the HTML code that displays the rankings for batting, bowling or scraping. In the batting rankings specifically, we can see that each row of the table corresponds to a <tr class="table-body"> tag that contains a player’s name, ranking, and rating. All the rankings (batting, bowling, and all-rounder) happen to follow this format.

Example row in rankings table from ICC Batting Rankings

As shown, a sample row contains several <td> tags that themselves store the information we are looking for. I noticed two types of <td> tags: the ones that contain relevant text at the outermost tag level like <td class="table-body__cell table-body__cell--position u-text-right">, and the ones that contain relevant text within their innermost nested tags like <td class="table-body__cell rankings-table__name name">. To avoid duplication of code, I created two functions to handle these common scenarios:

Both functions use BeautifulSoup’s find function, which finds and returns the first tag that with the specified “tag_name” and attributes. The functions return the text of the found tag after stripping it of any white-space.

get_outer_data_from_tag has the additional parameters “recursive=false” and “text=True” in its find function. These parameters ensure that we only look for text in the outermost tag rather than looking for tags or text in any nested tags.

Storing the Data

Ultimately, we need the data in an easy-to-manipulate format. I decided to use Pandas DataFrames since they not only display data easily, but also allow for fast and intuitive data transformations.

Building the DataFrame involves calling the parsing functions I discussed earlier. For every row in a ranking table, we created a dictionary with a player’s name, ranking, and rating. We appended this dictionary to a list of dictionaries and after traversing every row, we created a DataFrame from this list.

A simplified creation of a ranking DataFrame

As an example, the produced Pandas DataFrame for batting is shown below.

Batting Table

I constructed similar tables for bowling and all-rounder rankings, and I merged all the tables using the Pandas merge function. The result was a complete table with all of our data:

Full Table with Batting, Bowling, and All-Rounder Ratings

Findings

Once I had the data in a suitable form, I needed to find the equation that produced all-rounder ratings.

To do this, we define a new “X” matrix that contains the batting and bowling rating columns from our complete DataFrame. Our “Y” matrix contains the corresponding all-rounder rating column.

Now we need to find an equation that maps X to Y. In the simplest linear regression, this involves finding a coefficient for each variable in the X matrix. For our problem, this would mean finding a coefficient for the batting rating and one for the bowling rating. This resembled a linear combination of variables:

a * (batting rating) + b * (bowling rating) = all rounder rating

The approach that gives much better results involves assuming that the form of the equation is partially quadratic:

a * (batting rating) + b * (bowling rating) + c * (batting rating ) * (bowling rating) + d = all rounder rating

This means that the degree of our equation is two, but we only consider interaction terms beyond first degree variables.

Building X and Y matrices

The fit_transform function transforms the simple 2-column “X” matrix we defined to have 4 columns: one for a constant term, one for the batting rating, one for the bowling rating, and one for the product of the batting rating and the bowling rating (the “interaction term”).

Then we can run a linear regression on our new 4-column “X” matrix and the previously defined “Y” matrix.

If we examine our model’s coefficients, we would get an array of 4 values. Although we didn’t quite have enough data to get a completely noise-less formula, we see that all terms except the (batting rating) * (bowling rating) term go almost to zero with our produced coefficients. The coefficient for the interaction term ends up being roughly 1/1000, which matches formulas discussed elsewhere and helps keep the error for our model very low.

Conclusion

The all-rounder rating’s calculation is unique because of what it conveys. We can’t simply average a player’s batting and bowling rating to find their all-rounder rating because then a pure batsman or bowler would have a high all-rounder rating even though that player doesn’t have the skills of an all-rounder.

Instead, by multiplying the batting and bowling ratings and then dividing by 1000, we avoid promoting stellar specialist players to the top of the all-rounder rankings. In this sense, the all-rounder rating does a good job of reflecting how well a player can bat and bowl.

However, the all-rounder rating falls short because it doesn’t evaluate true “all-rounder” capabilities. For example, it doesn’t incorporate wicket-keeping or fielding skills, which are crucial aspects of a cricket match. The reason usually given for this deficiency is that there is no good way to measure these abilities. I suspect that will change as cricket becomes increasingly statistics-driven.

If you are interested in seeing or running the code, you can find it here. The approach I went over can be used to scrape cricket data for a different purpose or to analyze a different aspect of the rating system. I am curious to know what benefited you!

--

--