I’ve spent the last week or so doing a complete revamp of how I create GAA Senior County football club ratings and match predictions. I’ve also been working on developing attack and defense ratings for each club. It’s been an exciting project to work on and more tuning is definitely needed. But I’m pretty happy with how things have turned out and excited that I now have a live dashboard for this project!
Similar to how 538 posts long, long articles on the methodology for some of their dashboards, I’m going to do the same here – just probably not as in-depth or long.
I. How I create my Elo Ratings
I decided to use the Elo rating system to rank GAA football clubs partly because it’s fairly well-known, but also because I felt that it was a fairly simple system to get started with. Essentially, every team starts with a rating of 1500, which represents the rating that an average team would have. Depending on the results of head-to-head match-ups, teams will either gain or lose points. If Team A has a rating of 1510 and Team B has a rating of 1520, but Team A wins the game, then Team A will “take” points from Team B and their rating will improve while Team B’s will decrease.
In order to generate Elo ratings, I first had to gather all available data from the GAA fixtures and results page. The results on the site go back to 2016 and I know some folks out there have data going back way farther. I currently have 1,180 matches in my results data, which you can find here. It includes the date of the match, the clubs, each club’s points, goals, and total score, as well as the competition in which they played. I do my best to update the data every Monday after the weekend’s matches have been played and then run the new matches through my Elo rating code to see the results.
With the data collected, I next need to figure out some of the parameters I want in place when Elo ratings are calculated. Some Elo models take in A LOT of parameters – for example, in some baseball Elo models the starting pitcher, line-up, and how far the away team has to travel are all weighted into a team’s Elo rating before a game.
I don’t have the level of data granularity (yet) for GAA, so all of the Elo ratings are essentially generated as if each club is playing at a neutral site. It’s not ideal, but as more data becomes available I’ll be able to add more detailed parameters to the model.
After some data cleaning and wrangling, it’s time to create my 2 Elo parameters. The first one is the “K-factor”. The K-factor determines how the maximum number of points that can be gained or lost in a single game. If a K-factor is too high, ratings will jump around too much, but if it’s too low then it may not accurately reflect changes in team form.
After reading through some Elo documentation and articles, I’ve set the K-factor for my Elo ratings at 15. I didn’t do any maths to come up with the number, so it’s likely to change in future iterations (in fact, I do plan to eventually come up with a way to find the optimal K-factor). This means that the maximum amount of points a team can gain or lose is 15. If Dublin has an Elo of 1560 and Tyrone have a rating of 1460, and Tyrone pulls of an (unlikely) upset, then the best rating Tyrone could have after that match if 1475.
When determining each team’s post-match Elo rating, I also include the margin of victory. This is a pretty simple addition to the rating calculation – if a team wins by a large number of points, then they’ll get more points to their rating.
With the K-Factor now set at 15, I can now set the “carry-over” rate for each team. The carry-over rate determines how many points each team carries over from one season to the next. I don’t exactly follow how Nate Silver does it for his NBA ratings (I may update that once the 2023 season is over) but I set the carry-over rate at 50%. So if Monaghan started the season at 1550 and had a great season, ending with an Elo rating of 1600, then when the next season started they would begin with a rating of 1575.
II. Creating Attack & Defense Ratings
The next thing I wanted to do was to create attack rating and defense ratings for each team at the Senior County level for football. This was inspired by some Soccer Power Index (SPI) ratings that I’ve seen previously.
Each team is assigned attack and defense ratings based around what would be the expected amount of points, goals and the total score they would achieve in a match on average. The team’s defensive rating is just the inverse of their attack rating – how many points, goals, and the total score they’d be expected to concede.
Because my match results data contains a ‘team1’ and a ‘team2’ column, I had to split the data apart and then stack it back together. I grouped the data by team and competition year, giving me each team’s attacking and defensive ratings for each season from 2016 on-wards.

These ratings aren’t perfect, I’m not even sure if I should be calling them ratings, honestly. These are more like year-over-year averages, perhaps. These ratings are something I’d consider to be a 70% solution right now. Dublin’s score rating does track pretty well with their starting and ending Elo ratings, so I think there’s value in showing this. There just needs to be some improvement and tuning.
III. Match Predictions (In Development)
My match predictions are another area of this revamp that I consider to still be in “development”. Originally, my match predictions were simply generated based on each team’s Elo rating. Those teams that had higher ratings were always favored to win, which makes sense. The ratings are there for a reason – to distinguish between good, ok, and bad teams.
For my new match predictions, I want to incorporate each team’s attack and defense ratings, as well as their Elo rating. My hope is that this will make future predictions more accurate and informative than just saying that one time has a 60% chance of winning. The goal with new prediction format is also predict each team’s points, goals, and final score.
To do this, I went with a Monte Carlo simulation model, ran 10,000 times and incorporating a Poisson model to predict points, goals, and total score.

As of writing (evening of May 27), the first 3 games in the above table have been played. Here are the actual results:
- Louth 1-17 (20) v Cork 1-19 (22) ~ Verdict: meh
- Armagh 1-13 (16) v Westmeath 1-12 (15) ~ Verdict: ok
- Derry 0-14 (14) v Monaghan 0-14 (14) ~ Verdict: not that great, but interesting result!
Overall, I think that these predictions need continuous improvement. Armagh’s score was predicted spot-on, but the big miss was the Derry v Monaghan match. Derry has been rock-solid in my ratings model all year, so this was a pretty big miss. I haven’t watched the match or read about it yet, so I’m not exactly sure what happened here.
IV. The Way Ahead
The match predictions will continue to be refined, as well as the attack and defense ratings for each club. I’ll also need to add a tab in the dashboard specifically for the predictions.
Ideally, the dashboard and data will be automatically updated in the future. I’m not aware of any APIs for getting match data, so for now I’ll continue to add match results to my .csv file and running it my local R environment.
I’m definitely looking forward to continuing to work on this project and hopefully by the time the 2024 season rolls around, things are in a good state and there’s some stuff that’s been able to be automated.
By the way – I am not a trained statistician, mathematician, or data scientist. So if there are things in this methodology explainer that don’t make sense, or if anyone thinks the math could be done better, please let me know! I’d be happy to discuss and make the necessary changes.
Leave a Reply