{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
Peter Norvig
March 2019
\n", "\n", "# Baseball Simulation\n", "\n", "The [538 Riddler for March 22, 2019](https://fivethirtyeight.com/features/can-you-turn-americas-pastime-into-a-game-of-yahtzee/) asks us to simulate baseball using probabilities from a 19th century dice game called *Our National Ball Game*. The Riddler description of the rules said *you can assume some standard baseball things* but left many things unspecified, so I [looked up](http://baseballgames.dreamhosters.com/BbDiceHome.htm) the original rules of *Our National Ball Game*, which are shown below and which, it turns out, contradict some of the *standard baseball things* assumed by 538. I'll go with the rules as stated below.\n", "\n", "\n", "|RULES FOR PLAYING \"OUR NATIONAL BALL GAME\"|DICE ROLL OUTCOMES|\n", "|-----|-----|\n", "| ![](http://baseballgames.dreamhosters.com/bbOurNationalBallGameMcGillDelanyHoag86diE2.jpg) | ![](http://baseballgames.dreamhosters.com/bbOurNationalBallGameMcGillDelanyHoag86ddE.jpg) |\n", "\n", "*Note: There is a great history of dice baseball [here](https://baseballgames.dreamhosters.com/BbDiceHome.htm).*", "\n", "# Design Choices\n", "\n", "\n", "- Exactly one thing happens to each batter. I'll call that an **event**.\n", "- To clarify: the dice roll `1,1` has probability 1/36, whereas `1,2` has probability 2/36, because it also represents `2,1`.\n", "- The \"One Strike\" dice roll is not an event; it is only *part* of an event. From the probability of a \"One Strike\" dice roll, 7/36, I compute the probability of three strikes in a row, `(7/36)**3 == 0.00735`, and call that a strikeout event. \n", "- I'll represent events with the following 11 one letter **event codes**:\n", " - `1`, `2`, `3`, `4`: one-, two-, three-, and four-base (home run) hits. Runners advance same number of bases.\n", " - `B`: base on balls. Runners advance only if forced.\n", " - `D`: double play. Batter and runner nearest home are out; others advance one base.\n", " - `E`: error. Batter reaches first and all runners advance one base.\n", " - `F`, `K`, `O`: fly out, strikeout, foul out. Batter is out, runners do not advance.\n", " - `S`: called \"out at first\" in rules, but actually a sacrifice. Batter is out, runners advance one base.\n", "\n", "\n", "# Implementation" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import random\n", "from statistics import mean, stdev\n", "from collections import Counter\n", "from itertools import islice" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "event_codes = {\n", " '1': 'single', '2': 'double', '3': 'triple', '4': 'home run',\n", " 'B': 'base on balls', 'D': 'double play', 'E': 'error',\n", " 'F': 'fly out', 'K': 'strikeout', 'O': 'foul out', 'S': 'out at first'}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I'll define the function `inning` to simulate a half inning and return the number of runs scored. Design choices for `inning`:\n", "\n", "- I'll keep track of runners with a set of occupied bases; `runners = {1, 3}` means runners on first and third.\n", "- I'll keep track of the number of `runs` and `outs` in an inning, and return the number of `runs` when there are three `outs`.\n", "- Each event follows four steps. If `runners = {1, 3}` and the event is `'2'` (a double), then the steps are:\n", " - The batter steps up to the plate. The plate is represented as base `0`, so now `runners = {0, 1, 3}`.\n", " - Check if the event causes runner(s) to be out, and if the inning is over. In this case, no.\n", " - Advance each runner according to `advance(r, e)`. In this case, `runners = {2, 3, 5}`.\n", " - Remove the runners who have `scored` and increment `runs` accordingly. In this case, runner `5` has scored, so we increment `runs` by 1 and end up with `runners = {2, 3}`.\n", "- I want `inning` to be easily **testable**: I want to say `assert 2 = inning('1KO4F')`.\n", "- I also want `inning` to be capable of simulating many independent random innings. So the interface is to accept an *iterable* of event codes. That could be string, or a generator, as provided by `event_stream()`.\n", "- I want `inning` to be **loggable**: calling `inning(events, verbose=True)` should produce printed output for each event.\n", "- `advance(r, e)` says that a runner advances `e` bases on an `e` base hit; one base on an error, sacrifice, or double play; and one base on a base on balls only if forced.\n", "- A runner on base `r` is `forced` if all the lower-numbered bases have runners.\n", "- `ONBG` is defined as a generator of random events with the probabilities from \"Our National Ball Game\"." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def inning(events, verbose=True) -> int:\n", " \"\"\"Simulate a half inning based on events, and return number of runs scored.\"\"\"\n", " outs = runs = 0 # Inning starts with no outs and no runs,\n", " runners = set() # and with nobody on base\n", " def out(r) -> int: runners.remove(r); return 1\n", " def forced(r) -> bool: return all(b in runners for b in range(r))\n", " def advance(r, e) -> int: \n", " return int(e if e in '1234' else (e in 'ESD' or (e == 'B' and forced(r))))\n", " for e in events:\n", " if verbose: show(outs, runs, runners, e)\n", " runners.add(batter) # Batter steps up to the plate\n", " if e == 'D' and len(runners) > 1: # Double play: batter and lead runner out\n", " outs += out(batter) + out(max(runners))\n", " elif e in 'DSKOF': # Batter is out\n", " outs += out(batter) \n", " if outs >= 3: # If inning is over: return runs scored\n", " return runs \n", " runners = {r + advance(r, e) for r in runners} # Runners advance\n", " runs += len(runners & scored) # Tally runs\n", " runners = runners - scored # Remove runners who scored\n", " \n", "def event_stream(events, strikes=0):\n", " \"\"\"A generator of random baseball events.\"\"\"\n", " while True:\n", " yield 'K' if (random.random() < strikes ** 3) else random.choice(events)\n", "\n", "def show(outs, runs, runners, event):\n", " \"\"\"Print a representation of the current state of play.\"\"\"\n", " bases = ''.join(b if int(b) in runners else '-' for b in '321')\n", " print(f'{outs} outs {runs} runs {bases} {event} ({event_codes[event]})')\n", " \n", "ONBG = event_stream('2111111EEBBOOSSSSSSSFFFFFD334', 7/36) # Our National Ball Game\n", "batter = 0 # The batter is not yet at first base\n", "scored = {4, 5, 6, 7} # Runners in these positions have scored" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Examples and Tests\n", "\n", "Let's peek at some random innings:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- 3 (triple)\n", "0 outs 0 runs 3-- F (fly out)\n", "1 outs 0 runs 3-- S (out at first)\n", "2 outs 1 runs --- F (fly out)\n" ] }, { "data": { "text/plain": [ "1" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning(ONBG)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- F (fly out)\n", "1 outs 0 runs --- S (out at first)\n", "2 outs 0 runs --- S (out at first)\n" ] }, { "data": { "text/plain": [ "0" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning(ONBG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's also test some historic innings. I'll take some of the Red Sox innings from their 2004 playoff series against the Yankees." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- K (strikeout)\n", "1 outs 0 runs --- 2 (double)\n", "1 outs 0 runs -2- O (foul out)\n", "2 outs 0 runs -2- 1 (single)\n", "2 outs 0 runs 3-1 2 (double)\n", "2 outs 1 runs 32- 1 (single)\n", "2 outs 2 runs 3-1 4 (home run)\n", "2 outs 5 runs --- K (strikeout)\n" ] } ], "source": [ "# 7th inning in game 1: 5 runs (Homer by Varitek)\n", "# (But not a perfect reproduction, because our simulation doesn't have passed balls.)\n", "assert 5 == inning('K2O1214K')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- S (out at first)\n", "1 outs 0 runs --- S (out at first)\n", "2 outs 0 runs --- 2 (double)\n", "2 outs 0 runs -2- 1 (single)\n", "2 outs 0 runs 3-1 1 (single)\n", "2 outs 1 runs -21 4 (home run)\n", "2 outs 4 runs --- F (fly out)\n" ] } ], "source": [ "# 4th inning in game 6: 4 runs (Homer by Bellhorn)\n", "assert 4 == inning('SS2114F')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- S (out at first)\n", "1 outs 0 runs --- 1 (single)\n", "1 outs 0 runs --1 B (base on balls)\n", "1 outs 0 runs -21 B (base on balls)\n", "1 outs 0 runs 321 4 (home run)\n", "1 outs 4 runs --- B (base on balls)\n", "1 outs 4 runs --1 F (fly out)\n", "2 outs 4 runs --1 S (out at first)\n" ] } ], "source": [ "# 2nd inning in game 7: 4 runs (Grand Slam by Damon)\n", "assert 4 == inning('S1BB4BFS')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That looks good to me.\n", "\n", "# Simulation\n", "\n", "Now, simulate a hundred thousand innings, and then sample from them to simulate a hundred thousand nine-inning games (for one team), and show histograms of the results, labelled with statistics:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def simulate(N=100000, inning=inning, events=ONBG) -> None:\n", " innings = [inning(events=events, verbose=False) for _ in range(N)]\n", " games = [sum(random.sample(innings, 9)) for _ in range(N)]\n", " hist(innings, 'Runs/inning (for one team)')\n", " hist(games, 'Runs/game (for one team)')\n", " \n", "def hist(nums, title): \n", " \"\"\"Plot a histogram and show some statistics.\"\"\"\n", " plt.hist(nums, ec='black', bins=max(nums)-min(nums), align='left')\n", " plt.xlabel(title)\n", " plt.title(f'μ: {mean(nums):.2f}, σ: {stdev(nums):.2f}, max: {max(nums)}')\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.52 s, sys: 16.6 ms, total: 2.54 s\n", "Wall time: 2.58 s\n" ] } ], "source": [ "%time simulate()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, about 13 runs per game (per team). This shows that the dice game is not very realistic with respect to current-day baseball. It is true that games were higher-scoring 130 years ago, and perhaps a dice game is more fun when there is a lot of action.\n", "\n", "# Real Major League Baseball Stats\n", "\n", "Could I make the game reflect baseball as it is played today? To do so I would need:\n", "1. A source of major league baseball (MLB) statistics.\n", "2. A way to convert those statistics into the format expected by the function `inning`.\n", "3. Possibly some modifications to `inning`, depending on how the conversion goes.\n", "\n", "[Baseball-reference.com](https://www.baseball-reference.com) has lots of stats, in particular \n", "[MLB annual batting stats](https://www.baseball-reference.com/leagues/MLB/bat.shtml) and\n", "[fielding stats](https://www.baseball-reference.com/leagues/MLB/field.shtml); I'll use the stats for the complete 2019 season. The batting stats have most of what we need, and the fielding stats give us double plays and errors.\n", "\n", "I start by defining two utility functions that can be useful for any tabular data: `cell_value`, which converts a table cell entry into an `int`, `float`, or `str` as appropriate; and `header_row_dict`, which creates a dict of `{column_name: value}` entries. The function `mlb_convert` then converts this format (a dict keyed by `H/2B/3B/HR` etc.) into the event code format (a string of `'1234...'`). As part of the conversion I'll add hit-by-pitch (`HBP`) into the \"base on balls\" category, and I'll record all otherwise unaccounted-for outs under the \"fly out\" (`F`) category (runners do not advance). With this understood, we won't need to change the function `inning` at all. (It is true that `mlb_convert` returns a very long string, equal in length to the number of plate appearances over the whole MLB season. But that takes up less space than storing one photo, so I'm not going to worry about it.)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def cell_value(entry, types=(int, float, str)):\n", " \"\"\"Convert a cell entry into the first type that doesn't raise an error.\"\"\"\n", " for typ in types:\n", " try:\n", " return typ(entry)\n", " except ValueError:\n", " pass\n", " \n", "def header_row_dict(header, row, sep=None, value=cell_value) -> dict:\n", " \"\"\"Parse a header and table row into a dict of `{column_name: value(cell)}`.\"\"\"\n", " return dict(zip(header.split(sep), map(value, row.split(sep))))\n", "\n", "def mlb_convert(stats: dict) -> str:\n", " \"\"\"Given baseball stats return a string '11...FFF'.\"\"\"\n", " events = Counter({\n", " '1': stats['H'] - stats['2B'] - stats['3B'] - stats['HR'],\n", " '2': stats['2B'], '3': stats['3B'], '4': stats['HR'],\n", " 'E': stats['E'], 'B': stats['BB'] + stats['HBP'],\n", " 'K': stats['SO'], 'D': stats['DP'], 'S': stats['SH'] + stats['SF']})\n", " events['F'] = stats['PA'] - sum(events.values()) # All unaccounted-for outs\n", " return ''.join(events.elements()) # A str of events" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below I copy-and-paste the data I need from baseball-reference.com to create the dict `mlb_stats`; convert it to the string `mlb_string`; and use that to create the event generator `mlb_stream`:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "mlb_stats = header_row_dict(\n", " \"Year Tms #Bat BatAge R/G G PA AB R H 2B 3B HR RBI SB CS BB SO BA OBP SLG OPS TB GDP HBP SH SF IBB E DP\",\n", " \"\"\"2019 30 1284 27.9 4.84 4828 185377 165622 23346 41794 8485 783 6735 22358 2261 827 15806 42546 \n", " .252 .323 .435 .758 72050 3441 1968 774 1146 752 2882 3981\"\"\")\n", "mlb_string = mlb_convert(mlb_stats)\n", "mlb_stream = event_stream(mlb_string)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can take a look:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'Year': 2019,\n", " 'Tms': 30,\n", " '#Bat': 1284,\n", " 'BatAge': 27.9,\n", " 'R/G': 4.84,\n", " 'G': 4828,\n", " 'PA': 185377,\n", " 'AB': 165622,\n", " 'R': 23346,\n", " 'H': 41794,\n", " '2B': 8485,\n", " '3B': 783,\n", " 'HR': 6735,\n", " 'RBI': 22358,\n", " 'SB': 2261,\n", " 'CS': 827,\n", " 'BB': 15806,\n", " 'SO': 42546,\n", " 'BA': 0.252,\n", " 'OBP': 0.323,\n", " 'SLG': 0.435,\n", " 'OPS': 0.758,\n", " 'TB': 72050,\n", " 'GDP': 3441,\n", " 'HBP': 1968,\n", " 'SH': 774,\n", " 'SF': 1146,\n", " 'IBB': 752,\n", " 'E': 2882,\n", " 'DP': 3981}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mlb_stats" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'111111111111111111111111112222222223444444EEEBBBBBBBBBBBBBBBBBBKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKDDDDSSFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mlb_string[::1000] # Just look at every 1000th character" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- 2 (double)\n", "0 outs 0 runs -2- F (fly out)\n", "1 outs 0 runs -2- F (fly out)\n", "2 outs 0 runs -2- F (fly out)\n" ] }, { "data": { "text/plain": [ "0" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning(mlb_stream)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I can simulate:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYMAAAEWCAYAAACEz/viAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAd/ElEQVR4nO3deZhcVZ3/8fdnkrAoSxJoMKYTEjCA4G9A7F/AwQUNhsAwBp+RmTAOBM384ii4zijg+BhlccgwI8goaIRIUGQRRWIEYkAiihBpCGRhMW0IpCGQ1oQQRJaE7++Pc0ounep0V1V3Vy+f1/Pcp+89y72nbtdT3zr33DpXEYGZmQ1uf1XvBpiZWf05GJiZmYOBmZk5GJiZGQ4GZmaGg4GZmeFgYGZmOBhYnUj6rqSQ9KYO8veXdKOkNkkbJC2UdEC7Mp+R9JSkTZLmStqxl9p+e27Xs5IekDR1O2Xfk8tvkrSmTP64nP+8pIclHd2jje8Bkj4naYWkzZIelfS5dvldPl9WPw4G1uskvQPYr5Niw4H5wAHA3sBvgRsL+zgGOBOYBIwD9gW+0gPNLedTwKiI2A2YCXxf0qgOyv4JmAt8roP8q4GlwB7AfwDXS2ro5vb2NAGnACOAKcDpkqYV8is5X1YvEeHFS5cXIIA3FbavAM6toP5Q0offX7ffVyf1Rubye+TtHwBfLeRPAp7q4r52BL4JrAO25v0G8JMqzsdE4AVgYifljgbWtEvbH3gR2LWQ9ivgX7t47DWkILOMFHQuJwXOm4HNwK3AiEL5HwJPAZuAO4CDc/oOwP3AJ/L2EOBO4EtVvkcuBv63lvPlpfcX9wysW0l6Jn/z78hngDsiYlmFu34X6cP+j3n7YOCBQv4DwN6S9ujCvk4nfTi/HdiN9CG5OLcNSZdIumR7O5C0QNILwJJct7nLr+RVBwOrI2JzIe2BnN5Vfw+8jxRY/o4UCL4A7Enq+X+yUPZmYAKwF3AfcBVARLwE/DNwtqQ3k3pcQ4DzIPXkJD3TlcZIEvBOYGW79O44X9aDhta7ATawRMTwjvIkjQE+Crytkn1KaiR9k/9sIXkX0jfcktL6rsAf2b73AxdFxJq8/y+SPryeAIiIj3fWpog4XtIwUlA5MCJe6fyVbKP9ayBvj65gH/8bEU8DSPoVsD4ilubtG0g9plKb55bWJX0Z2Chp94jYFBErJJ0L3EDqXUyMiK253q9Jl+264sukIPTdYmI3nS/rQe4ZWG+6CDg7Itp/AHYoXz//OXBJRFxdyHqO9K2+pLRe/Jbdkb2Axwvbj5G+GFV0rT4iXo6Im4FjJL2/krpZ+9dA3u7Kayh5urD+5zLbuwBIGiLpfEm/l/Qs6RITpB5EyTzS+MtNEbGqgjaQj3E6aezgbyPixfb53XC+rAc5GFg1diqsd/UbI6RvqRfkO4Ceyml3SfqncoUljSAFgvkRcV677JXAIYXtQ4CnC5eRtqcVGF/YHg9s4bUfpJUYSucD4uWsBPaVtGsh7RDaXWLpJv8ETCV9M9+d9KEPafC35BJgAenDenuX+rYh6SPkAf2IaO2keLXny3qQg4FV48P5m+ahpA/4XfMlgM7sT/qwOzQvkK5z39C+oKTdgIXAnRFxZpl9XQnMkHRQDhpfJA1ml+ovzpdCyvke8GlJ+0raBfgqcG1EbOnsBUg6UNKxknaWNEzSP5PGM37ZQfm/krQTMCxtaidJOwBExO9IA7ezcvoHSAPrP8p1j5LUXXPM70oarP4j8DrSay6282TS5btTSeMM8/K56ZSkD+X9vS8iVrfLq+h8WR3VewTbS/9aSHfdXAqsB+4hDbo+AxyT858D3lnBvop3Jt0MfCGvT8/5f8r7LC1jC+U/S/o2/yzpGvWOhbzfkz6cyh1XpEHWx4A24PvA8EL+t4BvdVD3zaRB0M35dd8DfKCQ/07gucL2Ubx6t1JpWVzIH0caUP0z8AhwdCHvZOA32zl/a9qV/z7w5cL2vwC35vVdSLfmbs6v+5TS+QfGkoLEkYW61wLfKfeayrTjUeDldv+nb3XlfHnpO4vyP8ysS/I31QkR0VLvtnQkDzj/MCLeXu+21ELSZaTXsbDebbGBz8HAKtIfgoGZVc5jBmZm5p6BmZm5Z2BmZvTjXyDvueeeMW7cuHo3w8ysX7n33nv/EBHb/MCy3waDcePG0dzs6U3MzCoh6bFy6b5MZGZmDgZmZtaFYJCfILVe0ooyef+en1a1Z96WpIsltUhaJumwQtnpklblZXoh/W2Sluc6F+cpcM3MrBd1pWdwBenpRa+RpyN+H6+d/fFY0nzpE0hPNLo0lx0JzAIOJz3cYlaeT4ZcZmah3jbHMjOzntVpMIiIO4ANZbIuBD5Pmt+kZCpwZSR3A8Pz4+2OARZFxIaI2AgsAqbkvN0i4q5IP3i4EjihtpdkZmaVqmrMIM9F/kREPNAuazSwtrDdmtO2l95aJr2j486U1Cypua2trZqmm5lZGRUHA0mvIz24+0vlssukRRXpZUXEnIhoioimhob+9sxwM7O+q5qewX6kh4E8IGkN0AjcJ+kNpG/2YwplG4EnO0lvLJNuZma9qOJgEBHLI2KviBgXEeNIH+iHRcRTwHzglHxX0RHApohYR3pIyWRJI/LA8WRgYc7bLOmIfBfRKaQ5183MrBd15dbSq4G7gAMktUqasZ3iNwGrgRbgO8DHASJiA3AO6cEW95Ceg1salP4YcFmu83vSA04GhFGNY5FU8TKqcWy9m25mg0y/nbW0qakp+vp0FJLY54wFFdd7bPbx9Nf/i5n1bZLujYim9un+BXJfNGSYexNm1qv67UR1A9rWlyvuUTw2+/geaoyZDQbuGZiZmYOBmZk5GJiZGQ4GZmaGg4GZmeFgYGZmOBiYmRkOBmZmhoOBmZnhYGBmZjgYmJkZDgZmZoaDgZmZ4WBgZmY4GJiZGQ4GA4cfiGNmNfDDbQYKPxDHzGrgnoGZmTkYmJlZF4KBpLmS1ktaUUi7QNLDkpZJukHS8ELeWZJaJD0i6ZhC+pSc1iLpzEL6eElLJK2SdK2kHbrzBZqZWee60jO4ApjSLm0R8JaI+Gvgd8BZAJIOAqYBB+c6l0gaImkI8E3gWOAg4KRcFmA2cGFETAA2AjNqekVmZlaxToNBRNwBbGiX9vOI2JI37wYa8/pU4JqIeDEiHgVagIl5aYmI1RHxEnANMFWSgPcC1+f684ATanxNZmZWoe4YM/gIcHNeHw2sLeS15rSO0vcAnikEllJ6WZJmSmqW1NzW1tYNTTczM6gxGEj6D2ALcFUpqUyxqCK9rIiYExFNEdHU0NBQaXPNzKwDVf/OQNJ04HhgUkSUPsBbgTGFYo3Ak3m9XPofgOGShubeQbG8mZn1kqp6BpKmAGcA74+I5wtZ84FpknaUNB6YAPwWuAeYkO8c2oE0yDw/B5HbgQ/m+tOBG6t7KWZmVq2u3Fp6NXAXcICkVkkzgG8AuwKLJN0v6VsAEbESuA54ELgFOC0ituZv/acDC4GHgOtyWUhB5bOSWkhjCJd36ys0M7NOdXqZKCJOKpPc4Qd2RJwHnFcm/SbgpjLpq0l3G/VpoxrH8tQTazsvaGbWD3luoi566om1nvvHzAYsT0dhZmYOBmZm5mBgZmY4GJiZGQ4GZmaGg4GZmeFgYGZmOBiYmRkOBmZmhoOBmZnhYGBmZjgYmJkZDgaD25BhSKpoGdU4tt6tNrMe4FlLB7OtL3smVjMD3DMwMzMcDMzMDAcDMzPDwcDMzHAwMDMzHAzMzIwuBANJcyWtl7SikDZS0iJJq/LfETldki6W1CJpmaTDCnWm5/KrJE0vpL9N0vJc52JJ6u4XaWZm29eVnsEVwJR2aWcCt0XEBOC2vA1wLDAhLzOBSyEFD2AWcDgwEZhVCiC5zMxCvfbHMjOzHtZpMIiIO4AN7ZKnAvPy+jzghEL6lZHcDQyXNAo4BlgUERsiYiOwCJiS83aLiLsiIoArC/syM7NeUu2Ywd4RsQ4g/90rp48G1hbKtea07aW3lkkvS9JMSc2Smtva2qpsupmZtdfdA8jlrvdHFellRcSciGiKiKaGhoYqm2hmZu1VGwyezpd4yH/X5/RWYEyhXCPwZCfpjWXSzcysF1UbDOYDpTuCpgM3FtJPyXcVHQFsypeRFgKTJY3IA8eTgYU5b7OkI/JdRKcU9mVmZr2k01lLJV0NHAXsKamVdFfQ+cB1kmYAjwMn5uI3AccBLcDzwIcBImKDpHOAe3K5syOiNCj9MdIdSzsDN+fFzMx6UafBICJO6iBrUpmyAZzWwX7mAnPLpDcDb+msHWZm1nP8C2QzM3MwMDMzBwMzM8PBwMzMcDAwMzMcDMzMDAcDMzPDwcDMzHAwMDMzHAzMzAwHAzMzw8HAzMxwMDAzMxwMzMwMBwMzM2OQBoNRjWORVNFiZjaQdfpwm4HoqSfWss8ZCyqq89js43uoNWZm9TcoewZmZvZaDgZWmSHDKr7EJolRjWPr3XIz245BeZnIarD15YovsYEvs5n1de4ZmJlZbcFA0mckrZS0QtLVknaSNF7SEkmrJF0raYdcdse83ZLzxxX2c1ZOf0TSMbW9JDMzq1TVwUDSaOCTQFNEvAUYAkwDZgMXRsQEYCMwI1eZAWyMiDcBF+ZySDoo1zsYmAJcImlIte0yM7PK1XqZaCiws6ShwOuAdcB7getz/jzghLw+NW+T8ycp3cA/FbgmIl6MiEeBFmBije0yM7MKVB0MIuIJ4L+Bx0lBYBNwL/BMRGzJxVqB0Xl9NLA2192Sy+9RTC9T5zUkzZTULKm5ra2t2qabmVk7tVwmGkH6Vj8eeCPweuDYMkWjVKWDvI7St02MmBMRTRHR1NDQUHmjzcysrFouEx0NPBoRbRHxMvBj4G+A4fmyEUAj8GRebwXGAOT83YENxfQydczMrBfUEgweB46Q9Lp87X8S8CBwO/DBXGY6cGNen5+3yfm/iIjI6dPy3UbjgQnAb2tol5mZVajqH51FxBJJ1wP3AVuApcAc4GfANZLOzWmX5yqXA9+T1ELqEUzL+1kp6TpSINkCnBYRW6ttl5mZVa6mXyBHxCxgVrvk1ZS5GygiXgBO7GA/5wHn1dIWMzOrnn+BbGZmDgZmZuZgYGZmOBiYmRkOBmZmhoOBmZnhYGBmZjgYmJkZDgZmZoaDgZmZ4WBgZmY4GJiZGQ4GZmaGg4GZmeFgYGZmOBiYmRkOBmZmhoOBmZnhYGC9ZcgwJFW0jGocW+9Wmw0aNT0D2azLtr7MPmcsqKjKY7OP76HGmFl77hmYmVltwUDScEnXS3pY0kOS3i5ppKRFklblvyNyWUm6WFKLpGWSDivsZ3ouv0rS9FpflJmZVabWnsHXgVsi4kDgEOAh4EzgtoiYANyWtwGOBSbkZSZwKYCkkcAs4HBgIjCrFEDMzKx3VB0MJO0GvAu4HCAiXoqIZ4CpwLxcbB5wQl6fClwZyd3AcEmjgGOARRGxISI2AouAKdW2y8zMKldLz2BfoA34rqSlki6T9Hpg74hYB5D/7pXLjwbWFuq35rSO0rchaaakZknNbW1tNTTdzMyKagkGQ4HDgEsj4q3An3j1klA5KpMW20nfNjFiTkQ0RURTQ0NDpe01M7MO1BIMWoHWiFiSt68nBYen8+Uf8t/1hfJjCvUbgSe3k25mZr2k6mAQEU8BayUdkJMmAQ8C84HSHUHTgRvz+nzglHxX0RHApnwZaSEwWdKIPHA8OaeZmVkvqfVHZ58ArpK0A7Aa+DApwFwnaQbwOHBiLnsTcBzQAjyfyxIRGySdA9yTy50dERtqbJeZmVWgpmAQEfcDTWWyJpUpG8BpHexnLjC3lraYmVn1/AtkMzNzMDAzMwcDMzPDwcDMzHAwMDMzHAzMzAwHAzMzw8HAzMxwMDAzMxwMzMwMBwMzM8PBwMzMcDAwMzMcDMzMDAcDMzPDwcD6siHDkFTRMqpxbL1bbdYv1fqkM7Oes/Vl9jljQUVVHpt9fA81xmxgc8/AzMwcDMzMzMHAzMxwMDAzM7ohGEgaImmppAV5e7ykJZJWSbpW0g45fce83ZLzxxX2cVZOf0TSMbW2yczMKtMdPYNPAQ8VtmcDF0bEBGAjMCOnzwA2RsSbgAtzOSQdBEwDDgamAJdIGtIN7TIzsy6qKRhIagT+Frgsbwt4L3B9LjIPOCGvT83b5PxJufxU4JqIeDEiHgVagIm1tMvMzCpTa8/gIuDzwCt5ew/gmYjYkrdbgdF5fTSwFiDnb8rl/5Jepo6ZmfWCqoOBpOOB9RFxbzG5TNHoJG97ddofc6akZknNbW1tFbXXzMw6VkvP4Ejg/ZLWANeQLg9dBAyXVPplcyPwZF5vBcYA5PzdgQ3F9DJ1XiMi5kREU0Q0NTQ01NB0MzMrqjoYRMRZEdEYEeNIA8C/iIgPAbcDH8zFpgM35vX5eZuc/4uIiJw+Ld9tNB6YAPy22naZmVnlemJuojOAaySdCywFLs/plwPfk9RC6hFMA4iIlZKuAx4EtgCnRcTWHmiXmZl1oFuCQUQsBhbn9dWUuRsoIl4ATuyg/nnAed3RFjMzq5x/gWxmZg4GZmbmYGBmZjgYmJkZDgZmZoaDgQ00fm6yWVX8DGQbWPzcZLOquGdgZmYOBmZm5mBgZmY4GJiZGQ4GZmaGg4GZmeFgYGZmOBiYmRkOBmZmhoOBmZnhYGBmZjgYmJkZDgZmZoaDgZmZ4WBg5mcgmFHD8wwkjQGuBN4AvALMiYivSxoJXAuMA9YA/xARGyUJ+DpwHPA8cGpE3Jf3NR34Yt71uRExr9p2mVXMz0Awq6lnsAX4t4h4M3AEcJqkg4AzgdsiYgJwW94GOBaYkJeZwKUAOXjMAg4HJgKzJI2ooV1mZlahqoNBRKwrfbOPiM3AQ8BoYCpQ+mY/Dzghr08FrozkbmC4pFHAMcCiiNgQERuBRcCUattlZmaV65YxA0njgLcCS4C9I2IdpIAB7JWLjQbWFqq15rSO0ssdZ6akZknNbW1t3dF0MzOjG4KBpF2AHwGfjohnt1e0TFpsJ33bxIg5EdEUEU0NDQ2VN9bMzMqqKRhIGkYKBFdFxI9z8tP58g/57/qc3gqMKVRvBJ7cTrqZmfWSqoNBvjvocuChiPhaIWs+MD2vTwduLKSfouQIYFO+jLQQmCxpRB44npzTzMysl1R9aylwJHAysFzS/TntC8D5wHWSZgCPAyfmvJtIt5W2kG4t/TBARGyQdA5wTy53dkRsqKFdZmZWoaqDQUT8mvLX+wEmlSkfwGkd7GsuMLfatpiZWW38C2QzM3MwMKtKFVNYeBoL68tqGTMwG7yqmMICPI2F9V3uGZiZmYOBmZk5GJiZGQ4GZmaGg4GZmeFgYGZmOBiY9S4/YtP6KP/OwKw3+RGb1ke5Z2BmZg4GZmbmYGBmZjgYmPV9HnS2XuABZLO+zoPO1gvcMzAzMwcDMzNzMDAbmDzOYBXymIHZQORxBquQewZmlvhRnoNan+kZSJoCfB0YAlwWEefXuUlmg4sf5Tmo9YmegaQhwDeBY4GDgJMkHVTfVplZl3h8YkDoKz2DiUBLRKwGkHQNMBV4sK6tMrPOVTM+8d8fQFJFdYbssBNbX3qhx+sAvGH0GNa1Pl5xvf5MEVHvNiDpg8CUiPiXvH0ycHhEnN6u3ExgZt48AHikB5qzJ/CHHthvf+PzkPg8JD4PyUA4D/tEREP7xL7SMyj3FWGbKBURc4A5PdoQqTkimnryGP2Bz0Pi85D4PCQD+Tz0iTEDoBUYU9huBJ6sU1vMzAadvhIM7gEmSBovaQdgGjC/zm0yMxs0+sRloojYIul0YCHp1tK5EbGyTs3p0ctQ/YjPQ+LzkPg8JAP2PPSJAWQzM6uvvnKZyMzM6sjBwMzMHAxKJE2R9IikFkln1rs99SJpjaTlku6X1Fzv9vQmSXMlrZe0opA2UtIiSavy3xH1bGNv6OA8fFnSE/l9cb+k4+rZxt4gaYyk2yU9JGmlpE/l9AH5nnAwwNNhlPGeiDh0oN5PvR1XAFPapZ0J3BYRE4Db8vZAdwXbngeAC/P74tCIuKmX21QPW4B/i4g3A0cAp+XPhQH5nnAwSP4yHUZEvASUpsOwQSQi7gA2tEueCszL6/OAE3q1UXXQwXkYdCJiXUTcl9c3Aw8Boxmg7wkHg2Q0sLaw3ZrTBqMAfi7p3jz9x2C3d0Ssg/ThAOxV5/bU0+mSluXLSAPi0khXSRoHvBVYwgB9TzgYJF2aDmOQODIiDiNdMjtN0rvq3SDrEy4F9gMOBdYB/1Pf5vQeSbsAPwI+HRHP1rs9PcXBIPF0GFlEPJn/rgduIF1CG8yeljQKIP9dX+f21EVEPB0RWyPiFeA7DJL3haRhpEBwVUT8OCcPyPeEg0Hi6TAASa+XtGtpHZgMrNh+rQFvPjA9r08HbqxjW+qm9OGXfYBB8L5QmmP7cuChiPhaIWtAvif8C+Qs3yp3Ea9Oh3FenZvU6yTtS+oNQJqq5AeD6TxIuho4ijRN8dPALOAnwHXAWOBx4MSIGNCDqx2ch6NIl4gCWAN8tHTdfKCS9A7gV8By4JWc/AXSuMGAe084GJiZmS8TmZmZg4GZmeFgYGZmOBiYmRkOBmZmhoOBdTNJW/Oslisk/VTS8B46zi2S6j5liKQTJH0przdIWiJpqaR31rttJZKGS/p4Lxzn/0i6oqePYz3DwcC625/zrJZvIU12dlp3H0DSzsDIiHiiu/ddhc8Dl+T1ScDDEfHWiPhVVyrnGXN72nCgx4NBRCwHGiWN7eljWfdzMLCedBd5wj9JR0laUMqQ9A1Jp+b1NZK+Ium+/CyFA3P6uwvz5y8t/Tqa9AOoxbnMcZIelvRrSReXjiFpoqTf5Hq/kXRATj9V0k9yr+VRSadL+mwud7ekkbncfrn3ca+kX5XaVCRpf+DFiPiDpEOB/wKOy+3dWdJJ+fWskDS7UO85SWdLWgK8vd0+D83tWCbphtKEcJIWS5ot6beSflfqeUgaIukCSffkOh8t8384H9gvt+uCXO9zhTpfKRz/J/k1ryxOVJjbPDvn3ZrP72JJqyW9v3Csn5J+wW/9TUR48dJtC/Bc/jsE+CEwJW8fBSwolPsGcGpeXwN8Iq9/HLgsr/+UNHEewC7A0Lx+MfBeYCfSbLPjc/rVpWMAuxXKHw38KK+fCrQAuwINwCbgX3PehaTJyCDNUz8hrx8O/KLMa/0w8D+F7VOBb+T1N5J+ndpA+jX3L4ATcl4A/9DB+VsGvDuvnw1clNcXl44FHAfcmtdnAl/M6zsCzaXzUdjnOGBFYXsy6cHuIn0hXAC8K+eNzH93Jk05sUehzcfm9RuAnwPDgEOA+wv7PhL4ab3fh14qX9wzsO62s6T7gT8CI4FFXaxXmgTsXtKHF8CdwNckfRIYHhFbcvqRwK+BA4HVEfFoTr+6sL/dgR8qPa3rQuDgQt7tEbE5ItpIweCnOX05MC7PUvk3uf79wLeB4tw8JaOAtg5ez/8FFkdEW273VUBpBtitpMnPXkPS7vl1/jInzSvUgfLnaDJwSm7nEmAPYEIHbSqZnJelwH2k81iq80lJDwB3kyZvLKW/BNyS15cDv4yIl/N6qS2QJm17YyfHtz5oaL0bYAPOnyPi0PzBtoA0ZnAx6alRxS8fO7Wr92L+u5X8voyI8yX9jPRN+G5JR5M+lNZGxEt5IrGOnEP60P+A0lz0i8scC9KcMy8W1ofmdj4TEYd29lpJQaec7bXthYjY2sm+y9nmHOXjfCIiFlawHwH/GRHffk2idBSpF/X2iHhe0mJe/T+9HBGluWv+cs4i4hVJxc+RnUjnxfoZ9wysR0TEJuCTwL8rTQP8GHCQpB1zoJjU2T4k7RcRyyNiNunyx4Gk5yyUvqE+DOybP+wB/rFQfXegNMB8aoVtfxZ4VNKJuR2SdEiZog8Bb+pgN0uAd0vaMw8SnwT8soOypeNuAjYW7kQ6ubM6wELgY/kcI2l/pRlnizaTLosV63wk94CQNFrSXqRztjEHggNJj3qs1P4MghlNByIHA+sxEbEUeACYFhFrSTM9LiNdMlnahV18Og++PkD6tnkz6dm8t+T9/5k0xnCLpF+TZtjclOv+F/Cfku4kjV9U6kPAjHzslZR/DOodwFvL9VAizeh5FnA76RzcFxFdmep4OnCBpGWkWULP7qT8ZcCDwH35kti3adfjj4g/Anfmc3lBRPwc+AFwl6TlwPWkYHELMDQf+xzSpaJKvQf4WRX1rM48a6n1G5J2BO6MiKZC2i4R8Vz+QP4msCoiLuzFNn2dNGB6a28ds6/K/59fAu8ojO9YP+GegfUbEfFiMRBk/y8Pnq4kXeb49rY1e9RXgdf18jH7qrHAmQ4E/ZN7BmZm5p6BmZk5GJiZGQ4GZmaGg4GZmeFgYGZmwP8HkWLl1AemsFIAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.39 s, sys: 21.8 ms, total: 2.41 s\n", "Wall time: 2.46 s\n" ] } ], "source": [ "%time simulate(events=mlb_stream)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That looks a *lot* more like real baseball. But MLB averaged 4.84 runs per team per game in 2019, and this is significantly lower. I think we can make some minor changes to the function `inning`—some \"standard baseball things\"—to make the simulation more realistic. I'm thinking of two changes:\n", "- The most common double play eliminates the batter and the runner on first, not the runner closest to home. \n", "- On a single, a runner on second often scores. \n", "\n", "I'll make those two things the case for all double plays and singles." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def inning2(events, verbose=False) -> int:\n", " \"\"\"Simulate a half inning based on events, and return number of runs scored.\"\"\"\n", " outs = runs = 0 # Inning starts with no outs and no runs,\n", " runners = set() # and with nobody on base\n", " def out(r) -> int: runners.remove(r); return 1\n", " def forced(r) -> bool: return all(b in runners for b in range(r))\n", " def advance(r, e) -> int: \n", " return ((2 if r == 2 else int(e)) if e in '1234' else \n", " (e in 'ESD' or (e == 'B' and forced(r)))) \n", " for e in events:\n", " if verbose: show(outs, runs, runners, e)\n", " runners.add(batter) # Batter steps up to the plate\n", " if e == 'D' and 1 in runners: # Double play: batter and runner on first out\n", " outs += out(batter) + out(1)\n", " elif e in 'DSKOF': # Batter is out\n", " outs += out(batter) \n", " if outs >= 3: # If inning is over: return runs scored\n", " return runs \n", " runners = {r + advance(r, e) for r in runners} # Runners advance\n", " runs += len(runners & scored) # Tally runs\n", " runners = runners - scored # Remove runners who scored" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We show the difference with two examples. First, a triple/walk/double-play sequence scores a run under `inning2` but not `inning`:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- 3 (triple)\n", "0 outs 0 runs 3-- B (base on balls)\n", "0 outs 0 runs 3-1 D (double play)\n", "2 outs 1 runs --- K (strikeout)\n" ] }, { "data": { "text/plain": [ "1" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning2('3BDK', True)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- 3 (triple)\n", "0 outs 0 runs 3-- B (base on balls)\n", "0 outs 0 runs 3-1 D (double play)\n", "2 outs 0 runs -2- K (strikeout)\n" ] }, { "data": { "text/plain": [ "0" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning('3BDK', True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Second, a double/single sequence scores a run under `inning2` but not `inning`:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- 2 (double)\n", "0 outs 0 runs -2- 1 (single)\n", "0 outs 1 runs --1 F (fly out)\n", "1 outs 1 runs --1 F (fly out)\n", "2 outs 1 runs --1 F (fly out)\n" ] }, { "data": { "text/plain": [ "1" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning2('21FFF', True)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 outs 0 runs --- 2 (double)\n", "0 outs 0 runs -2- 1 (single)\n", "0 outs 0 runs 3-1 F (fly out)\n", "1 outs 0 runs 3-1 F (fly out)\n", "2 outs 0 runs 3-1 F (fly out)\n" ] }, { "data": { "text/plain": [ "0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inning('21FFF', True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can simulate again and note any differences:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "scrolled": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.37 s, sys: 17.1 ms, total: 2.39 s\n", "Wall time: 2.41 s\n" ] } ], "source": [ "%time simulate(events=mlb_stream, inning=inning2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is a slight increase in the number of runs.\n", "\n", "# Opportunities for Improvement\n", "\n", "There are many problems with the code as it is. For example:\n", "\n", "- It assumes all teams are equal. They're not.\n", "- It assumes all pitchers and defense are equal. They're not.\n", "- It assumes all batters are equal. They're not. (I think this is the main place where we get a shortfall in runs: real lineups cluster their best hitters together, and they are more apt to produce runs than a lineup of all median players.)\n", "- It assumes all hits are the same (runners always advance the same number of bases). They're not.\n", "- There's only one type of double play (batter and runner on first out) and no triple play.\n", "- It ignores stolen bases, pickoffs, passed balls, wild pitches, runners taking extra bases, and runners being out on attempted steals, extra bases, or sacrifices.\n", "- There is no strategy (offense and defense behave the same, regardless of the situation).\n", "- It assumes both teams bat for 9 innings. But if the home team is ahead at the bottom of the 9th, they do not bat, and if the score is tied: extra innings.\n", "- With two outs, or with no runners on base, there can be no sacrifice or double play; those types of events would just be regular outs. The stats say that a double play should occur in 3981 out of 185377 at bats, or about 2% of the time. In our simulation the `D` event code would come up that often, but perhaps only half the time there would be a runner and less than two outs, so we would only actually get a double play maybe 1% of the time.\n", "\n", "\n", "What can you do to make the simulation better?" ] } ], "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.7.6" } }, "nbformat": 4, "nbformat_minor": 2 }