Grappling Analysis - Best Fights and Promotions
Goal
Systematically rank the MMA fights based on their grappling components. Activity and competitiveness are the main attributes desired here. There are many great grappling performances that were quick and one sided but here I’m looking for fights where both fighters had some level as success.
Data Collection
Used Selenium with Headless Chrome to scrape fight stats from ufcstats.com. Put into a Pandas dataframe with features:
column_names = ["Weightclass", "Submission", "Rounds", "Date", "A_name", "A_takedowns", "A_takedown_attempts", "A_ground_strikes", "A_ground_strike_ratio", "A_sub_attempts", "A_passes", "A_reversals", "B_name", "B_takedowns", "B_takedown_attempts", "B_ground_strikes", "B_ground_strike_ratio", "B_sub_attempts", "B_passes", "B_reversals"]
"Weightclass"
- String - What weight the fight was held at
"Submission"
- Boolean - Whether or not the fight ended with a Submission
"Rounds"
- int - How many rounds the bout lasted
"Date"
- datetime - When the bout took place
"A_name"
- String - the name of Fighter A
"A_takedowns"
- Int - The number of takedowns completed by fighter A
"A_takedowns_attempts"
- Int - The number of takedowns attempted by fighter A (complete + incomplete)
"A_ground_strikes"
- Int - Number of strikes landed by fighter A while on the ground
"A_ground_strike_ratio"
- Float - A_ground_strikes / total number of strikes
"A_sub_attempts"
- Int - The number of Submission attempts attempted by fighter B
"A_passes"
- Int - The number of times fighter A passed fighter B’s guard
A_reversals
- Int - The number of times fighter A swept or reversed fighter
The columns for fighter B follow the above definitions
Fights with this form were gathered separately for the UFC, WEC, Strikeforce and Pride organizations and merged together when needed for analysis.
Data Cleaning & Engineering
Calculating Grapple Score
def getGrappleScore(fight):
A_score = 1
A_score += 0.75 * fight.A_takedowns
A_score += (1/4) * fight.A_takedown_attempts
A_score += 1.75 * fight.A_passes
A_score += 3 * fight.A_reversals
A_score += 2.5 * fight.A_sub_attempts
A_score += (0.2 * fight.A_ground_strike_ratio) * fight.A_ground_strikes
B_score = 1
### ...
### Same as above
### ...
B_score += (0.2 * fight.B_ground_strike_ratio) * fight.B_ground_strikes
Fight_Score = fight.Submission * 4 + (A_score + B_score) * (1 - ((max(A_score,B_score) - min(A_score,B_score))**1.5/max(A_score,B_score)**1.5)) * (1 - fight.Rounds * .05)
return Fight_Score
ufc_df['Score'] = ufc_df.apply(lambda X: getGrappleScore(X), axis=1)
wec_df['Score'] = wec_df.apply(lambda X: getGrappleScore(X), axis=1)
strikeforce_df['Score'] = strikeforce_df.apply(lambda X: getGrappleScore(X), axis=1)
pride_df['Score'] = pride_df.apply(lambda X: getGrappleScore(X), axis=1)
A_score = 1
A_score += 0.75 * fight.A_takedowns
A_score += (1/4) * fight.A_takedown_attempts
A_score += 1.75 * fight.A_passes
A_score += 3 * fight.A_reversals
A_score += 2.5 * fight.A_sub_attempts
A_score/B_score are started at 1 to avoid a potential division by 0 error. Otherwise the individual scores are just a linear combination of the fighter’s grappling stats with different weights. Reversals are highly rewarded because they indicate an exchange in which both fighters had some level of success. Submission attempts, passes, takedowns and takedown attempts were likewise scaled by how much I believed they contributed to an active grappling match.
A_score += (0.2 * fight.A_ground_strike_ratio) * fight.A_ground_strikes
Ground strikes, being the easiest stat to accumulate, were a bit more difficult to factor in and were scaled down to no dominate the score. In lieu of being able to find stats regarding total time on the ground I also used ground_strike_ratio in this term as an approximation of top control time (the fighter on top usually lands significant strikes at a much higher rate). If a fighter has a high ground strike ratio it’s likely they spent a significant portion of the fight on top of their opponent instead of on the bottom or just standup.
Fight_Score = fight.Submission * 4 + (A_score + B_score) * (1 - ((max(A_score,B_score) - min(A_score,B_score))**1.5/max(A_score,B_score)**1.5)) * (1 - fight.Rounds * .05)
fight.Submission * 4
- Rewarding a fight for ending in a Submission
(A_score + B_score)
- Sum of both fighters scores
((max(A_score,B_score) - min(A_score,B_score))**1.5/max(A_score,B_score)**1.5)
- Returns a number in [0.0, 1.0], the closer to 1 the closer the fight scores for each fighter were. I found the term on its own was too punishing and the term squared wasn’t enough so settled at raising the term to the power of 1.5.
(1 - fight.Rounds * .05)
- Fights with more rounds will naturally have more stats accumulated so this term makes the fight score consider that.
Results
Top 25 Grappling Fights:
Fighter A | Fighter B | Score |
---|---|---|
Louis Smolka | Tim Elliott | 52.593 |
Nate Diaz | Alejandro Garcia | 49.244 |
John Alessio | Alex Serdyukov | 47.303 |
Russell Doane | Jerrod Sanders | 46.976 |
Ed Herman | Kendall Grove | 45.07 |
Magomed Magomedov | Petr Yan | 44.818 |
Chris Wade | Islam Makhachev | 44.595 |
Antonio Rodrigo Nogueira | Bob Sapp | 44.47 |
Michinori Tanaka | Kyung Ho Kang | 44.219 |
Matt Grice | Jason Black | 40.897 |
Kevin Holland | Gerald Meerschaert | 40.41 |
John Hathaway | Rick Story | 40.199 |
Cub Swanson | Micah Miller | 39.002 |
Carlos Condit | Jake Ellenberger | 38.847 |
Heath Herring | Cheick Kongo | 38.615 |
Chase Beebe | Rani Yahya | 38.329 |
Dan Henderson | Yuki Kondo | 38.309 |
Quinton Jackson | Murilo Rua | 38.096 |
Demian Maia | Jason MacDonald | 36.977 |
Paddy Holohan | Louis Smolka | 36.839 |
Gerald Meerschaert | Oskar Piechota | 36.689 |
Ricardo Lamas | Dave Jansen | 36.466 |
Dan Henderson | Murilo Rua | 36.355 |
Jared Hamman | Rodney Wallace | 36.267 |
Ben Rothwell | Gilbert Yvel | 36.13 |
Grappling Score by Promotion:
All promotions share a very similar, extremely right skewed distributions; close to a geometric. This is a product of many fights having no grappling components at all or if they do, then they’re extremely one sided. Pride & WEC have noticeably higher means and this aligns with my ‘eyeball’ test.
Pride’s events took place in the early to mid 2000’s when the grappling meta wasn’t close to where it is today. WEC mostly featured fights in the lighter weight classes, 155lbs and lower, where physical attributes naturally lead to more scrambles and exciting grappling exchanges.