VCT 2023 Champions Analysis
Probability a team wins a map
Posted on August 2023
I am interested in finding the probability of a team win a map in VCT Champions. Prior to this, I realized that Paperrex (PRX), usually perform a comeback and won a map. So, I want to analyze the probability of a team won a map based on their round difference.
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from IPython.display import Image, display
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
data_path = "VCT2023_rounddiffs_team_map_playoff_data.xlsx"
df = pd.read_excel(data_path, index_col=None)
df.head()
Team | Round diffs | Map | |
---|---|---|---|
0 | LOUD | 0 | Ascent |
1 | LOUD | 1 | Ascent |
2 | LOUD | 2 | Ascent |
3 | LOUD | 3 | Ascent |
4 | LOUD | 4 | Ascent |
df.dtypes
Team object
Round diffs int64
Map object
dtype: object
sns.set_theme(style='whitegrid')
palette = {"LOUD":"tab:green",
"PRX":"tab:purple",
"DRX":"tab:cyan",
"EDG":"tab:red",
"EG":"tab:blue",
"FNATIC":"tab:orange",
"BLG":"tab:pink"}
sns.kdeplot(data=df, x="Round diffs", hue="Team", fill=True, common_norm=False, palette=palette).set(title="Probability Density of Round Differences when a Team Won a Map")
[Text(0.5, 1.0, 'Probability Density of Round Differences when a Team Won a Map')]
sns.kdeplot(data=df, x="Round diffs", hue="Team", cumulative=True, common_norm=False, palette=palette).set(title="Cumulative Density of Round Differences when a Team Won a Map")
[Text(0.5, 1.0, 'Cumulative Density of Round Differences when a Team Won a Map')]
Probability a team win the map when they have negative round differences
To obtain the probability, I used kernel density estimation to estimate the distribution of teams winning a map based on their round difference. Then I caculate the area under the curve that is less than 0.
# Probability winning a negative round diffs
teams = df["Team"].unique()
probability = []
for team in teams:
ax = sns.kdeplot(data=df[df["Team"] == team], x="Round diffs",common_norm=False, color="blue")
# Get all the lines used to draw the density curve
kde_lines = ax.get_lines()[-1]
kde_x, kde_y = kde_lines.get_data()
# Mask area under the curve that less than 0
mask = kde_x < 0
filled_x, filled_y = kde_x[mask], kde_y[mask]
# Area of less than 0
area = np.round(np.trapz(filled_y, filled_x)*100, 2)
probability.append(area)
result = pd.DataFrame([teams, probability]).T
result.columns = ["Team", "Probability a team win the map when they have negative round differences (in %)"]
result.sort_values(by="Probability a team win the map when they have negative round differences (in %)", ascending=False, inplace=True)
fig, ax = plt.subplots(figsize=(10, 6))
ax = sns.barplot(data=result, x="Probability a team win the map when they have negative round differences (in %)", y="Team", palette=palette)
images = [plt.imread(team + ".png") for team in result["Team"]]
tick_labels = ax.yaxis.get_ticklabels()
ax.set(yticklabels=[])
ax.set(xticklabels=[])
ax.set(ylabel=None)
ax.grid(False)
for i in ax.containers:
ax.bar_label(i,)
for i,image in enumerate(images):
ib = OffsetImage(image, zoom=.15)
ib.image.axes = ax
ab = AnnotationBbox(ib,
tick_labels[i].get_position(),
frameon=False,
box_alignment=(1.25, 0.5)
)
ax.add_artist(ab)
In general as I hypothesize earlier, PRX has the highest probability to win a map when they down a round followed by DRX.
Probability a team win the map when they have -6 round differences
# Probability winning a -6 round difference
teams = df["Team"].unique()
probability = []
for team in teams:
ax = sns.kdeplot(data=df[df["Team"] == team], x="Round diffs",common_norm=False, color="blue")
# Get all the lines used to draw the density curve
kde_lines = ax.get_lines()[-1]
kde_x, kde_y = kde_lines.get_data()
# Mask area under the curve that less than -6
mask = kde_x < -6
filled_x, filled_y = kde_x[mask], kde_y[mask]
# Area of less than -6
area = np.round(np.trapz(filled_y, filled_x)*100, 2)
#print("The probability that {} won a map when experiences 9-3 curse is: {}%".format(team, area))
probability.append(area)
sns.set_theme(style='whitegrid')
sns.kdeplot(data=df, x="Round diffs", hue="Team", fill=True, common_norm=False, palette=palette).set(title="Probability Density of Round Differences when a Team Won a Map")
plt.axvline(x=-6, linewidth=2, linestyle='--')
<matplotlib.lines.Line2D at 0x29be734c990>
result = pd.DataFrame([teams, probability]).T
result.columns = ["Team", "Probability a team win the map when they down 6 rounds (in %)"]
result.sort_values(by="Probability a team win the map when they down 6 rounds (in %)", ascending=False, inplace=True)
ax = sns.barplot(data=result, x="Probability a team win the map when they down 6 rounds (in %)", y="Team", palette=palette)
images = [plt.imread(team + ".png") for team in result["Team"]]
tick_labels = ax.yaxis.get_ticklabels()
ax.set(yticklabels=[])
ax.set(xticklabels=[])
ax.set(ylabel=None)
ax.grid(False)
for i in ax.containers:
ax.bar_label(i,)
for i,image in enumerate(images):
ib = OffsetImage(image, zoom=.15)
ib.image.axes = ax
ab = AnnotationBbox(ib,
tick_labels[i].get_position(),
frameon=False,
box_alignment=(1.25, 0.5)
)
ax.add_artist(ab)
However, when we consider a “comeback” though (here I defined a comeback as winning with less than -6 round differences), DRX takes the spot. However, DRX is skewed because they have one match against BLG in which they comeback from -10 round differences.