{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Analyzing the dataset of LoL's champions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"https://www.kaggle.com/datasets/uskeche/leauge-of-legends-champions-dataset?resource=download"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read the data"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"Dat = pd.read_csv(\"LoLChampions.csv\")\n",
"Dat = Dat.drop(\"Id\", axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Data quality and data preprocessing"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first thing that we should do is to check the quality of the data set."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Name | \n",
" Class | \n",
" Style | \n",
" Difficulty | \n",
" DamageType | \n",
" Damage | \n",
" Sturdiness | \n",
" Crowd-Control | \n",
" Mobility | \n",
" Functionality | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Aatrox | \n",
" Warrior | \n",
" 3 | \n",
" 2 | \n",
" P | \n",
" 3 | \n",
" 3 | \n",
" 2 | \n",
" 2 | \n",
" 2.0 | \n",
"
\n",
" \n",
" 1 | \n",
" Ahri | \n",
" Mage | \n",
" 10 | \n",
" 2 | \n",
" M | \n",
" 3 | \n",
" 1 | \n",
" 2 | \n",
" 3 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 2 | \n",
" Akali | \n",
" Assasin | \n",
" 7 | \n",
" 2 | \n",
" PM | \n",
" 3 | \n",
" 1 | \n",
" 1 | \n",
" 3 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 3 | \n",
" Alistar | \n",
" Tank-Support | \n",
" 7 | \n",
" 1 | \n",
" M | \n",
" 1 | \n",
" 3 | \n",
" 3 | \n",
" 1 | \n",
" 2.0 | \n",
"
\n",
" \n",
" 4 | \n",
" Amumu | \n",
" Tank | \n",
" 9 | \n",
" 1 | \n",
" M | \n",
" 2 | \n",
" 3 | \n",
" 3 | \n",
" 1 | \n",
" 1.0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Name Class Style Difficulty DamageType Damage Sturdiness \\\n",
"0 Aatrox Warrior 3 2 P 3 3 \n",
"1 Ahri Mage 10 2 M 3 1 \n",
"2 Akali Assasin 7 2 PM 3 1 \n",
"3 Alistar Tank-Support 7 1 M 1 3 \n",
"4 Amumu Tank 9 1 M 2 3 \n",
"\n",
" Crowd-Control Mobility Functionality \n",
"0 2 2 2.0 \n",
"1 2 3 1.0 \n",
"2 1 3 1.0 \n",
"3 3 1 2.0 \n",
"4 3 1 1.0 "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Dat.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Style | \n",
" Difficulty | \n",
" Damage | \n",
" Sturdiness | \n",
" Crowd-Control | \n",
" Mobility | \n",
" Functionality | \n",
"
\n",
" \n",
" \n",
" \n",
" count | \n",
" 145.000000 | \n",
" 145.000000 | \n",
" 145.000000 | \n",
" 145.000000 | \n",
" 145.000000 | \n",
" 145.000000 | \n",
" 144.000000 | \n",
"
\n",
" \n",
" mean | \n",
" 6.544828 | \n",
" 1.882759 | \n",
" 2.434483 | \n",
" 1.662069 | \n",
" 2.013793 | \n",
" 1.717241 | \n",
" 1.465278 | \n",
"
\n",
" \n",
" std | \n",
" 2.806192 | \n",
" 0.702213 | \n",
" 0.715054 | \n",
" 0.774782 | \n",
" 0.726351 | \n",
" 0.742588 | \n",
" 0.668086 | \n",
"
\n",
" \n",
" min | \n",
" 1.000000 | \n",
" 1.000000 | \n",
" 1.000000 | \n",
" 1.000000 | \n",
" 0.000000 | \n",
" 1.000000 | \n",
" 1.000000 | \n",
"
\n",
" \n",
" 25% | \n",
" 4.000000 | \n",
" 1.000000 | \n",
" 2.000000 | \n",
" 1.000000 | \n",
" 2.000000 | \n",
" 1.000000 | \n",
" 1.000000 | \n",
"
\n",
" \n",
" 50% | \n",
" 7.000000 | \n",
" 2.000000 | \n",
" 3.000000 | \n",
" 1.000000 | \n",
" 2.000000 | \n",
" 2.000000 | \n",
" 1.000000 | \n",
"
\n",
" \n",
" 75% | \n",
" 9.000000 | \n",
" 2.000000 | \n",
" 3.000000 | \n",
" 2.000000 | \n",
" 3.000000 | \n",
" 2.000000 | \n",
" 2.000000 | \n",
"
\n",
" \n",
" max | \n",
" 10.000000 | \n",
" 3.000000 | \n",
" 3.000000 | \n",
" 3.000000 | \n",
" 3.000000 | \n",
" 3.000000 | \n",
" 3.000000 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Style Difficulty Damage Sturdiness Crowd-Control \\\n",
"count 145.000000 145.000000 145.000000 145.000000 145.000000 \n",
"mean 6.544828 1.882759 2.434483 1.662069 2.013793 \n",
"std 2.806192 0.702213 0.715054 0.774782 0.726351 \n",
"min 1.000000 1.000000 1.000000 1.000000 0.000000 \n",
"25% 4.000000 1.000000 2.000000 1.000000 2.000000 \n",
"50% 7.000000 2.000000 3.000000 1.000000 2.000000 \n",
"75% 9.000000 2.000000 3.000000 2.000000 3.000000 \n",
"max 10.000000 3.000000 3.000000 3.000000 3.000000 \n",
"\n",
" Mobility Functionality \n",
"count 145.000000 144.000000 \n",
"mean 1.717241 1.465278 \n",
"std 0.742588 0.668086 \n",
"min 1.000000 1.000000 \n",
"25% 1.000000 1.000000 \n",
"50% 2.000000 1.000000 \n",
"75% 2.000000 2.000000 \n",
"max 3.000000 3.000000 "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Dat.describe()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can observe that there are missing values in the Functionality variable."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Name | \n",
" Class | \n",
" Style | \n",
" Difficulty | \n",
" DamageType | \n",
" Damage | \n",
" Sturdiness | \n",
" Crowd-Control | \n",
" Mobility | \n",
" Functionality | \n",
"
\n",
" \n",
" \n",
" \n",
" 23 | \n",
" Ekko | \n",
" Mage-Warrior | \n",
" 8 | \n",
" 3 | \n",
" M | \n",
" 3 | \n",
" 2 | \n",
" 2 | \n",
" 3 | \n",
" NaN | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Name Class Style Difficulty DamageType Damage Sturdiness \\\n",
"23 Ekko Mage-Warrior 8 3 M 3 2 \n",
"\n",
" Crowd-Control Mobility Functionality \n",
"23 2 3 NaN "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Dat[Dat[\"Functionality\"].isnull()]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are other issues regarding the quality of the data. For example, the type of the variables, several of them should be categorical.\n",
"\n",
"For now, we are going to keep the data set as it is, since these issues won't compromise our analysis."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Name object\n",
"Class object\n",
"Style int64\n",
"Difficulty int64\n",
"DamageType object\n",
"Damage int64\n",
"Sturdiness int64\n",
"Crowd-Control int64\n",
"Mobility int64\n",
"Functionality float64\n",
"dtype: object"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Dat.dtypes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Imagine that we select a champion at random (all of them with the same probability of being selected)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Classical probability\n",
"\n",
"By classical probability, if we want to estimate the probability of the event $A$, we can do it as: $$P(A)=\\frac{1}{n}\\sum_{i=1}^n 1(\\text{observation}_i\\text{ satisfies A}).$$\n",
"\n",
"Which is just the average of $1(\\text{observation}\\text{ satisfies A})$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is the prob. of select a class warrior?"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.2138"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"round((Dat[\"Class\"]==\"Warrior\").mean(), 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conditional Probability\n",
"\n",
"For conditional probabilities, we have, at least, two different ways to calculate them.\n",
"\n",
"For instance, if we want to calculate the probability of $P(A|B)$, we can do it as:\n",
"\n",
"1. Filter for the observations where the event $B$ happened. Then, calculate the probability of $A$ considering only those observations.\n",
"2. Calculate it using the definition of conditional probability, i.e. $$P(A|B)=\\frac{P(A,B)}{P(B)}$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is the prob. of selecting a class warrior given that it is of difficulty 1?\n",
"\n",
"Let's do it first using the filtering approach:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.2444"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Filter the observtions to consider only the champions where difficulty=1\n",
"DatDifficult1 = Dat[Dat[\"Difficulty\"]==1]\n",
"\n",
"# Calculate the probability of selecting a class warrior, considering only the observations previosly filtered\n",
"round((DatDifficult1[\"Class\"]==\"Warrior\").mean(), 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using the definition:\n",
"\n",
"1. We need to calculate the join probability of selecting a class warrior and a difficulty equal 1: $$P(\\text{warrior and difficulty=1})$$\n",
"2. We need to calculate the marginal probability of selecting a champion of difficulty 1 $$P(\\text{difficulty=1})$$\n",
"3. We need to divide the former probability by the later: $$P(\\text{warrior|difficulty=1})=\\frac{P(\\text{warrior and difficulty=1})}{P(\\text{difficulty=1})}$$"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.2444"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"PWarriorAndDifficult1 = ((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==1)).mean()\n",
"PDifficult1 = (Dat[\"Difficulty\"]==1).mean()\n",
"\n",
"PWarriorGivenDifficult1 = PWarriorAndDifficult1 / PDifficult1\n",
"\n",
"round(PWarriorGivenDifficult1, 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multiplication law or chain rule\n",
"\n",
"Consider that we want to calculate the probability of the events $A$, $B$, and $C$ at the same time, i.e. $P(A\\cap B\\cap C)$.\n",
"\n",
"The multiplication law, says that such probability can be calculated as: $$P(A\\cap B\\cap C)=P(A|B,C)P(B|C)P(C)$$\n",
"\n",
"Note that, it doesn't matter the order in which we condition."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is the prob. of selecting a class warrior, difficulty 1, and style 4?\n",
"\n",
"First, let's calculate it using the deffinition of classical probability"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0207"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"round(((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==1) & (Dat[\"Style\"]==4)).mean(), 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, let's calculate it using the multiplication law:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.5\n",
"0.46153846153846156\n",
"0.0896551724137931\n"
]
}
],
"source": [
"# Probability of being warrior given that it is difficulty 1 and style 4\n",
"print(((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==1) & (Dat[\"Style\"]==4)).mean() / ((Dat[\"Difficulty\"]==1) & (Dat[\"Style\"]==4)).mean())\n",
"\n",
"# Probability of difficulty 1 given style 4\n",
"print(((Dat[\"Difficulty\"]==1) & (Dat[\"Style\"]==4)).mean() / (Dat[\"Style\"]==4).mean())\n",
"\n",
"# Probability of style 4\n",
"print((Dat[\"Style\"]==4).mean())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thus, the probability that we are looking for should be the product of these three probabilities"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.0207"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"round(0.5 * 0.46153846153846156 * 0.0896551724137931, 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Law of total probability\n",
"\n",
"Law of total probability stays that, if $B_1,B_2,B_3,\\ldots$ form a partition of $\\Omega$, i.e. $\\cup_{i}B_i=\\Omega$ and $B_i\\cap B_j=\\emptyset$ for all $i\\neq j$. Then, $$P(A)=\\sum_iP(A|B_i)P(B_i)=\\sum_i P(A,B_i)$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is the prob. of selecting a warrior?\n",
"\n",
"First, let's calculate this probability using classical probability"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.2138"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"round((Dat[\"Class\"]==\"Warrior\").mean(), 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, let's calculate it using law of total probability.\n",
"\n",
"Note that, every champion should be of difficulty 1, 2, or 3. So the events $B_i:$ the champion is of difficulty $i$, form a partition of $\\Omega$.\n",
"\n",
"Thus, the probability of selecting a warrior can be calculate it as: $$P(\\text{warrior})=P(\\text{warrior and difficulty 1}) + P(\\text{warrior and difficulty 2}) + P(\\text{warrior and difficulty 3})$$"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.07586206896551724\n",
"0.09655172413793103\n",
"0.041379310344827586\n"
]
}
],
"source": [
"print(((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==1)).mean())\n",
"print(((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==2)).mean())\n",
"print(((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==3)).mean())"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.2138"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"round(0.07586206896551724 + 0.09655172413793103 + 0.041379310344827586, 4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Bayes' theorem"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is the probability of selecting a warrior given that it is of difficulty 1?\n",
"\n",
"We already calculated that probability previously."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.24444444444444444"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"PWarriorGivenDifficult1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We are going to calculate it again. But this time, we are going to use Bayes' theorem.\n",
"\n",
"Accordign to Bayes' theorem, the probability that we are looking for, can be calculated as:\n",
"\n",
"$$P(\\text{Warrior|Difficulty=1})=\\frac{P(\\text{Difficulty=1|Warrior})P(\\text{Warrior})}{P(\\text{Difficulty=1})}$$"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.2444"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"PDifficult1GivenWarrior = ((Dat[\"Class\"]==\"Warrior\") & (Dat[\"Difficulty\"]==1)).mean() / (Dat[\"Class\"]==\"Warrior\").mean()\n",
"PWarrior = (Dat[\"Class\"]==\"Warrior\").mean()\n",
"PDifficult1 = (Dat[\"Difficulty\"]==1).mean()\n",
"\n",
"round(PDifficult1GivenWarrior * PWarrior / PDifficult1, 4)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}