diff --git a/stories/2023-02-01-Overwatch-League/OWL_story.ipynb b/stories/2023-02-01-Overwatch-League/OWL_story.ipynb index 521f412..fc01bec 100644 --- a/stories/2023-02-01-Overwatch-League/OWL_story.ipynb +++ b/stories/2023-02-01-Overwatch-League/OWL_story.ipynb @@ -34,7 +34,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "|
|\n", + "### Reviewers:\n", + "- David Llewellyn-Jones\n", + "- Jack Roberts" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "|![Overwatch League Logo](preview.png){width=600}|\n", "|:-:| \n", "| Overwatch League Logo courtesy of Blizzard Entertainment.|" ] @@ -59,7 +68,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "|
|\n", + "|![Screenshot of Overwatch gameplay](gameplay01.jpg){width=800}|\n", "|:-:| \n", "| Overwatch gameplay from the player's point of view. Image credit Blizzard Entertainment. |" ] @@ -121,9 +130,10 @@ "id": "y4Cnt1XoDTVF" }, "source": [ - "\n", "# Part 1. Data ingestion\n", "\n", + "\n", + "\n", "### Data source\n", "\n", "The official OWL website includes a stats tab that contains various data on players, heroes (characters players can choose), and matches. For this analysis, we will be using the [match data](https://overwatchleague.com/en-us/statslab) as it includes the results of match ups between different teams in the league. Blizzard provides the data for anyone to analyse, but unfortunately it does not come with an explicit free data license that would allow us to redistribute it." @@ -150,13 +160,12 @@ "- data extraction (zipfile, requests)\n", "- data visualisation (pyplot, seaborn)\n", "- machine learning and statistical modelling (sklearn) \n", - "- notebook widgets (widgets, IPython.display)\n", "- utilities (io, itertools, random)" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": { "id": "9ZVLUkRQlT_9" }, @@ -169,7 +178,6 @@ "from zipfile import ZipFile\n", "\n", "from IPython.display import clear_output\n", - "import ipywidgets as widgets\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "import numpy as np\n", @@ -671,9 +679,10 @@ "id": "7rhbsSHoHlSn" }, "source": [ - "\n", "# Part 2. Data cleaning\n", "\n", + "\n", + "\n", "Next we reduce the data to only the information that we need." ] }, @@ -1211,9 +1220,10 @@ "id": "wb_NCIQJI9xz" }, "source": [ - "\n", "# Part 3. Initial data exploration\n", "\n", + "\n", + "\n", "Our eventual goal is to predict the outcomes of future games based on past history of the teams involved. For example, a predictor should be able to use information from the first 200 games to predict the result of the 201st game.\n", "\n", "Before we do that however, let's start with exploring the data to get an initial idea of what it looks like and how teams perform. We start by collecting lists of all maps and teams." @@ -1618,97 +1628,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "|
|\n", + "|![The Temple of Anubis Overwatch map](templeofanubis_anno_1024.png){width=600}|\n", "|:-:| \n", "| A top-down schematic of one of the most popular maps, Temple of Anubis. This is an Assault type map, where the attacking team starts at the bottom right and tries to capture the two capture points, A and B, from the defenders. Image made by [statbanana](https://statbanana.com/images). |" ] }, - { - "cell_type": "markdown", - "metadata": { - "id": "1XiKBeo2LLDT" - }, - "source": [ - "If you're curious about a particular team's performance, you can use the below widget to browse how they did on each map." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 396, - "referenced_widgets": [ - "89d91a44b6794629a3d2bcbd54c5c4ca", - "98d2c26d8b564f07a1bd03559a4ae1b4", - "e5da3a3c399b4b8f99820104e213a27f", - "f4ff65f65f8547719d20a62e7fd2d2ae", - "afd59a3108dd4370ab393150896dac2d" - ] - }, - "id": "Np0VPUABbpXD", - "outputId": "440773fd-63d1-4376-ff69-44273e52b965" - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "75749fa36392412791e00b4856069790", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Dropdown(description='Team Name', options=('Los Angeles Valiant', 'Shanghai Dragons', 'Guangzhou Charge', 'Los…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7ad2dcd10a0c47e9a2049f6601e6a463", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "out = widgets.Output()\n", - "\n", - "# See https://ipywidgets.readthedocs.io/en/latest/\n", - "# for what widgets are.\n", - "def on_team_selection(change):\n", - " with out:\n", - " clear_output()\n", - " team = team_selector.value\n", - " team_filter = all_teams_map_data[\"team_name\"] == change[\"new\"]\n", - " print(all_teams_map_data[team_filter].to_string(index=False))\n", - "\n", - "\n", - "team_selector = widgets.Dropdown(\n", - " options=team_names, value=None, description=\"Team Name\"\n", - ")\n", - "display(team_selector)\n", - "display(out)\n", - "team_selector.observe(on_team_selection, names=\"value\")" - ] - }, { "cell_type": "markdown", "metadata": { "id": "JupHOOJ1NUUF" }, "source": [ - "\n", - "# Part 4. A benchmark predictor" + "# Part 4. A benchmark predictor\n", + "\n", + "" ] }, { @@ -1912,8 +1845,9 @@ "id": "KGjg51ytQvQv" }, "source": [ - "\n", - "# Part 5. Higher win rate predictor" + "# Part 5. Higher win rate predictor\n", + "\n", + "" ] }, { @@ -2683,7 +2617,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "|
|\n", + "|![Screenshot of Overwatch gameplay](gameplay03.jpg){width=800}|\n", "| :--: |\n", "| Overwatch players can choose from many characters, called heroes, with different abilities. We don't use any data specific to choices of heroes, nor do we use information particular to the different game modes, but simply focus on the question of which team won against which team on which map. Image credit Blizzard Entertainment. |" ] @@ -2694,9 +2628,10 @@ "id": "wWxuO8QtkTu9" }, "source": [ - "\n", "# Part 6. Skill based predictor - Elo ratings\n", "\n", + "\n", + "\n", "The map win rate predictor may have been a bit better than random guessing, but it certainly isn't blowing our socks off. Let's now try something more interesting.\n", "\n", "For competitive games, it is natural to introduce some kind of skill based system, where higher skilled teams are considered more likely to win than lower skilled teams. One such system, originally developed for chess, is called [Elo ratings](https://en.wikipedia.org/wiki/Elo_rating_system). We will use it here." @@ -3384,7 +3319,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "|
|\n", + "|![Photo of professional Overwatch player mid-game](blizzcon2019_player.jpg){width=700}|\n", "| :--: |\n", "| Professional Overwatch players in a tournament. We model skill using Elo ratings on the level of teams, not individual players. Image credit Blizzard Entertainment. |" ] @@ -3572,8 +3507,9 @@ "id": "VLM2RBNc2jJ1" }, "source": [ - "\n", - "# Part 7: Conclusions" + "# Part 7: Conclusions\n", + "\n", + "" ] }, {