My Brazilian Jiu Jitsu (BJJ) Journey
The following project is an attempt to quantitatively and visually document my progression in Brazilian jiu jitsu.
Brazilian jiu jitsu, hereafter referred to as BJJ, originated in the early 20th century in Brazil, evolving from Japanese jujitsu and judo. BJJ is a martial art based on grappling, ground fighting, and submission holds. It approaches self-defense by emphasizing taking an opponent to the ground, gaining a dominant position, and using various techniques to force them into submission via joint locks or chokeholds. Thanks to its remarkable success in modern mixed martial arts (MMA), BJJ has grown exceptionally fast over the last decade, attracting people from all walks of life to try this unique martial art.
In the practice of BJJ, there are two main training approaches — gi and no gi.
The distinction between gi and no gi in BJJ refers to the type of clothing worn during training or competition, which in turn affects the techniques and strategies employed. In gi jiu jitsu, practitioners wear a traditional uniform known as a gi, consisting of a jacket, pants, and a belt. The gi provides grips and handles for controlling an opponent, simulating scenarios where an attacker might be wearing clothing. On the other hand, no gi jiu jitsu, commonly referred to as submission grappling, is practiced without the traditional gi uniform. Practitioners typically wear rashguards and shorts. Without the gi to grip, the focus shifts to controlling the opponent through body positioning, underhooks, and overhooks.
BJJ employs a belt system to signify a practitioner's level of skill and experience. The belt colors, in ascending order of proficiency, are white, blue, purple, brown, and black. Each belt level signifies a milestone in a practitioner's journey, with the transition from one belt to the next typically taking an average of two to four years.
I began training BJJ in January 2022 and got promoted to blue belt in August 2023, about a month after I started recording data for this project. Therefore, this project will essentially measure my progression from blue belt onward.
My goal with this project is to quantify my fighting style, identify strengths and weaknesses, and use that information to set goals and prioritize areas of improvement in my training. The visualizations generated in this project will help answer questions such as what are my preferred submissions, how am I most frequently submitted, which positions do I tend to favor, and if there are any positions from which my defensive abilities are comparatively weaker. Submissions and positions will be complemented with contextual information such as my belt rank, my opponent's belt rank, and whether a submission was in gi or no gi training. More on the dataset later.
Given the nature of the sport, this project will primarily focus on submissions. It's important to acknowledge this inherent limitation right from the outset. BJJ encompasses many more dimensions than just submissions. In fact, the majority of a fight is about achieving the position from which a submission could be applied. This includes takedowns, sweeps, transitions, defensive escapes, and more. Sparring in BJJ requires full concentration, and I don't want to detract from that by attempting to memorize every detail of the fight. Therefore, my attention will be focused on the culmination of these actions — submissions and their associated positions.
The dataset I will be working with is being manually constructed by me using Google Sheets and imported here using the Google Cloud API. This workspace automatically updates as I input new data after my training sessions. I plan to continuously add and refine my analysis as more data becomes available, but above all, I envision this project evolving into a "business" intelligence tool that I can consult as I continue to progress with my training.
Let's import the dataset and go through the variables.
%%capture
!pip install gspread
from google.oauth2 import service_account
import pandas as pd
import base64
import gspread
import json
import os
import plotly.express as px
import plotly.graph_objects as go
# Set up the environment
google_json_base64 = os.environ.get("GOOGLE_JSON_BASE64")
google_json = base64.b64decode(google_json_base64).decode('ascii')
service_account_info = json.loads(google_json)
credentials = service_account.Credentials.from_service_account_info(service_account_info)
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
creds_with_scope = credentials.with_scopes(scope)
client = gspread.authorize(creds_with_scope)
spreadsheet = client.open_by_url('https://docs.google.com/spreadsheets/d/1V32Z2aVZmyEz1WNoA9huEWOer_RzgiC1e9jDiKi7sl4/edit#gid=0')
worksheet = spreadsheet.get_worksheet(0)
records_data = worksheet.get_all_records()
Data
I record eight variables in the dataset:
- Date: The date associated with each submission
- Submissions by: The type of submission when I submit someone
- Submitted by: The type of submissions when someone submits me
- Position: The position associated with the submission
- Belt: My belt rank
- Stripe: The number of stripes on my belt (stripes represent different levels within a belt; each belt can have up to four stripes)
- Opponent's belt: My opponent's belt rank
- Gi/No gi: Whether the training is in gi or no gi
Submission by
and Submitted by
are mutually exclusive columns, meaning each row is associated with either me submitting someone or someone submitting me.
# Load the dataset
submissions = pd.DataFrame.from_dict(records_data)
submissions.head(10)
# Replace empty strings with 'null'
submissions = submissions.replace('', None)
In this workspace, I will limit my focus on high-level insights:
- Submissions: Overall distribution of total submmissions applied by me and applied to me
- Positions: The distribution of positions for when I submit someone and when someone submits me
- Submissions by: The types of submissions applied by me, overall and categorized by position
- Submitted by: The types of submissions applied to me, overall and categorized by position
See the table of contents to navigate between the sections.
While we have the option to further dissect these insights using variables such as Gi/No gi
, Belt
, Stripe
, and Opponent's belt
, we should be cautious not to overload the workspace with excessive detail. For more granular analysis based on these variables, I've developed a Looker dashboard that allows for easy filtering.
Submissions
Do I submit to people more often, or do they submit to me more?
Submissions are the ultimate goal of a BJJ match. There's a popular saying among BJJ practitioners: "Sometimes you're the hammer, sometimes you're the nail." Let's see if I'm the hammer or the nail more often.
total_subs_by = submissions["submission_by"].count()
total_subbed_by = submissions["submitted_by"].count()
subs_dist = pd.DataFrame({
"Category": ["Submissions", "Submitted"],
"Count": [total_subs_by, total_subbed_by]
})
# Create a pie chart for total submissions vs submitted
subs_plot = px.pie(subs_dist,
names="Category",
values="Count",
title="<b>Submissions vs Submitted<b>")
subs_plot.update_traces(marker=dict(colors=["#3f7f93", "#c3553a"]),
texttemplate="<b>%{percent:.0%}<b>",
textfont=dict(size=20),
hovertemplate="<b>%{label}</b>: %{value}")
subs_plot.update_layout(title_font=dict(size=22, color="black"),
legend=dict(traceorder="reversed", x=0, y=0.5, font=dict(size=16)))
subs_plot.show()
Positions
If you’ve trained BJJ, you’re likely familiar with the phrase “position before submission.” Achieving a successful submission is only possible after effectively controlling your opponent, which requires a dominant position. While there are many positions in BJJ, they could be grouped into the following categories:
- Top: Submissions applied from mount, side control, and knee-on-belly
- Bottom: Submissions applied from closed guard, half-guard, or any variation of open guard
- Back: Submissions applied from the back
- Legs: Submissions applied to the legs