\n",
"\n",
- "# Dice Baseball\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*:\n",
- "\n",
- " 1,1: double 2,2: strike 3,3: out at 1st 4,4: fly out\n",
- " 1,2: single 2,3: strike 3,4: out at 1st 4,5: fly out\n",
- " 1,3: single 2,4: strike 3,5: out at 1st 4,6: fly out\n",
- " 1,4: single 2,5: strike 3,6: out at 1st 5,5: double play\n",
- " 1,5: base on error 2,6: foul out 5,6: triple\n",
- " 1,6: base on balls 6,6: home run\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",
- "The rules left some things unspecified; the following are my current choices (in an early version I made different choices that resulted in slightly more runs):\n",
+ "|RULES FOR PLAYING \"OUR NATIONAL BALL GAME\"|DICE ROLL OUTCOMES|\n",
+ "|-----|-----|\n",
+ "|  |  |\n",
"\n",
- "* On a* b*-base hit, runners advance* b* bases, except that a runner on second scores on a 1-base hit.\n",
- "* On an \"out at first\", all runners advance one base.\n",
- "* A double play only applies if there is a runner on first; in that case other runners advance.\n",
- "* On a fly out, a runner on third scores; other runners do not advance.\n",
- "* On an error all runners advance one base. \n",
- "* On a base on balls, only forced runners advance.\n",
+ "# Design Choices\n",
"\n",
- "I also made some choices about the implementation:\n",
"\n",
- "- Exactly one outcome happens to each batter. We call that an *event*.\n",
- "- I'll represent events with the following one letter codes:\n",
- " - `K`, `O`, `o`, `f`, `D`: strikeout, foul out, out at first, fly out, double play\n",
- " - `1`, `2`, `3`, `4`: single, double, triple, home run\n",
- " - `E`, `B`: error, base on balls\n",
- "- Note the \"strike\" dice roll is not an event; it is only part of an event. From the probability of a \"strike\" dice roll, I compute the probability of three strikes in a row, and call that a strikeout event. Sice there are 7 dice rolls giving \"strike\", the probability of a strike is 7/36, and the probability of a strikeout is (7/36)**3.\n",
- "- Note that a die roll such as `1,1` is a 1/36 event, whereas `1,2` is a 2/36 event, because it also represents (2, 1).\n",
- "- I'll keep track of runners with a list of occupied bases; `runners = [1, 2]` means runners on first and second.\n",
- "- A runner who advances to base 4 or higher has scored a run (unless there are already 3 outs).\n",
- "- The function `inning` simulates a half inning and returns the number of runs scored.\n",
- "- I want to be able to test `inning` by feeding it specific events, and I also want to generate random innings. So I'll make the interface be that I pass in an *iterable* of events. The function `event_stream` generates an endless stream of randomly sampled events.\n",
- "- Note that it is consider good Pythonic style to automatically convert Booleans to integers, so for a runner on second (`r = 2`) when the event is a single (`e = '1'`), the expression `r + int(e) + (r == 2)` evaluates to `2 + 1 + 1` or `4`, meaning the runner on second scores.\n",
- "- I'll play 1 million innings and store the resulting scores in `innings`.\n",
- "- To simulate a game I just sample 9 elements of `innings` and sum them.\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",
- "# The Code"
+ "\n",
+ "# Implementation"
]
},
{
@@ -53,9 +39,11 @@
"metadata": {},
"outputs": [],
"source": [
- "%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
- "import random"
+ "import random\n",
+ "from statistics import mean, stdev\n",
+ "from collections import Counter\n",
+ "from itertools import islice"
]
},
{
@@ -64,85 +52,82 @@
"metadata": {},
"outputs": [],
"source": [
- "def event_stream(events='2111111EEBBOOooooooofffffD334', strike=7/36):\n",
- " \"An iterator of random events. Defaults from `Our National Ball Game`.\"\n",
- " while True:\n",
- " yield 'K' if (random.random() < strike ** 3) else random.choice(events)\n",
- " \n",
- "def inning(events=event_stream(), 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 = [] # ... and with nobody on base\n",
- " for e in events:\n",
- " if verbose: print(f'{outs} outs, {runs} runs, event: {e}, runners: {runners}')\n",
- " # What happens to the batter?\n",
- " if e in 'KOofD': outs += 1 # Batter is out\n",
- " elif e in '1234EB': runners.append(0) # Batter becomes a runner\n",
- " # What happens to the runners?\n",
- " if e == 'D' and 1 in runners: # double play: runner on 1st out, others advance\n",
- " outs += 1\n",
- " runners = [r + 1 for r in runners if r != 1]\n",
- " elif e in 'oE': # out at first or error: runners advance\n",
- " runners = [r + 1 for r in runners]\n",
- " elif e == 'f' and 3 in runners and outs < 3: # fly out: runner on 3rd scores\n",
- " runners.remove(3)\n",
- " runs += 1\n",
- " elif e in '1234': # single, double, triple, homer\n",
- " runners = [r + int(e) + (r == 2) for r in runners]\n",
- " elif e == 'B': # base on balls: forced runners advance \n",
- " runners = [r + forced(runners, r) for r in runners]\n",
- " # See if inning is over, and if not, whether anyone scored\n",
- " if outs >= 3:\n",
- " return runs\n",
- " runs += sum(r >= 4 for r in runners)\n",
- " runners = [r for r in runners if r < 4]\n",
- " \n",
- "def forced(runners, r) -> bool: return all(b in runners for b in range(r))"
+ "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": [
- "# Testing\n",
+ "I'll define the function `inning` to simulate a half inning and return the number of runs scored. Design choices for `inning`:\n",
"\n",
- "Let's peek at some random innings:"
+ "- 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": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0 outs, 0 runs, event: E, runners: []\n",
- "0 outs, 0 runs, event: 4, runners: [1]\n",
- "0 outs, 2 runs, event: E, runners: []\n",
- "0 outs, 2 runs, event: 1, runners: [1]\n",
- "0 outs, 2 runs, event: f, runners: [2, 1]\n",
- "1 outs, 2 runs, event: B, runners: [2, 1]\n",
- "1 outs, 2 runs, event: 1, runners: [3, 2, 1]\n",
- "1 outs, 4 runs, event: E, runners: [2, 1]\n",
- "1 outs, 4 runs, event: o, runners: [3, 2, 1]\n",
- "2 outs, 5 runs, event: o, runners: [3, 2]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "5"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
- "inning(verbose=True)"
+ "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:"
]
},
{
@@ -154,20 +139,16 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "0 outs, 0 runs, event: 1, runners: []\n",
- "0 outs, 0 runs, event: B, runners: [1]\n",
- "0 outs, 0 runs, event: O, runners: [2, 1]\n",
- "1 outs, 0 runs, event: 1, runners: [2, 1]\n",
- "1 outs, 1 runs, event: 3, runners: [2, 1]\n",
- "1 outs, 3 runs, event: 1, runners: [3]\n",
- "1 outs, 4 runs, event: f, runners: [1]\n",
- "2 outs, 4 runs, event: o, runners: [1]\n"
+ "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": [
- "4"
+ "1"
]
},
"execution_count": 4,
@@ -176,14 +157,7 @@
}
],
"source": [
- "inning(verbose=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And we can feed in any events we want to test the code:"
+ "inning(ONBG)"
]
},
{
@@ -195,22 +169,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "0 outs, 0 runs, event: 2, runners: []\n",
- "0 outs, 0 runs, event: E, runners: [2]\n",
- "0 outs, 0 runs, event: B, runners: [3, 1]\n",
- "0 outs, 0 runs, event: B, runners: [3, 2, 1]\n",
- "0 outs, 1 runs, event: 1, runners: [3, 2, 1]\n",
- "0 outs, 3 runs, event: D, runners: [2, 1]\n",
- "2 outs, 3 runs, event: B, runners: [3]\n",
- "2 outs, 3 runs, event: 1, runners: [3, 1]\n",
- "2 outs, 4 runs, event: 2, runners: [2, 1]\n",
- "2 outs, 5 runs, event: f, runners: [3, 2]\n"
+ "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": [
- "5"
+ "0"
]
},
"execution_count": 5,
@@ -219,36 +186,40 @@
}
],
"source": [
- "inning('2EBB1DB12f', verbose=True)"
+ "inning(ONBG)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "That looks good.\n",
- "\n",
- "# Simulating\n",
- "\n",
- "Now, simulate a million innings, and then sample from them to simulate a million nine-inning games (for one team):"
+ "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": [],
+ "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": [
- "N = 1000000\n",
- "innings = [inning() for _ in range(N)]\n",
- "games = [sum(random.sample(innings, 9)) for _ in range(N)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's see histograms:"
+ "# 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')"
]
},
{
@@ -257,35 +228,90 @@
"metadata": {},
"outputs": [
{
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
+ "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": [
- "def hist(nums, title): \n",
- " \"Plot a histogram.\"\n",
- " plt.hist(nums, ec='black', bins=max(nums)-min(nums)+1, align='left')\n",
- " plt.title(f'{title} Mean: {sum(nums)/len(nums):.3f}, Min: {min(nums)}, Max: {max(nums)}')\n",
- " \n",
- "hist(innings, 'Runs per inning:')"
+ "# 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",
+ "image/png": "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\n",
"text/plain": [
""
]
@@ -294,10 +320,506 @@
"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": [
- "hist(games, 'Runs per game:')"
+ "%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": "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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.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": "iVBORw0KGgoAAAANSUhEUgAAAYkAAAEWCAYAAACT7WsrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAfRklEQVR4nO3de7xVdZ3/8dc7kMQroGgEFFZ4n5H0hDhmY1II5og9Jh+DU3IyGiYjzZmpCfv9Jn6ZNjqXLk5p4ygjOKaZZZKDIZF0MW/HSyCScSKFEygnQcIsSfz8/ljfo8vD/p699+Gcsw/wfj4e+7HX+qzvWuu7Njz2e6/LWUsRgZmZWSWvaXQHzMys/3JImJlZlkPCzMyyHBJmZpblkDAzsyyHhJmZZTkkzMwsyyFhfUrSX0t6UtLvJH1H0rAa5mmWFJI+XKrdIem50murpOW92/uX1z1G0l2Snpf0c0nv6qLtSEm3SdooqU3SR0rTDk3T2tP0RZIO64tt6EmS3pk+j82SnqgwvebPy/ofh4T1GUlHAf8JnAMcDDwPXFllnqHARcCKcj0ipkTEPh0v4KfAN3ul49u7EXgYOAD4P8AtkoZn2v4P8CuK7X0P8HlJ70zThgALgMPS9PuB23qx373ld8Bc4JOZ6fV8XtbfRIRfftX8AgJ4S2n8OuCSGuf9PPD10vibga3Avl3M8zXgo8BS4MOZNmOAbcAhNfbjtcBXgfVpvkiv79Qw76HAC+U+Az8GPlKh7T5pucNLtauB6zPLHpbaH1DjdjxB8cW8jOKL+lqKsLkD2AJ8Hxhaav9N4ClgM/Aj4KhUHwQ8ApyfxgcAdwOfqfP/xruAJ7r7efnVP1/ek7AeJelZSW/PTD4K+FnHSET8kiIkDs0sazzQRBEUXZkO/DgiflVjNz9G8YV2ArAfxZfnUuDv0nqvlJTbwzkKWB0RW0q1n6X6dpvQ6b1j+OjMst8BPBURz9SwDR3+Eng3xWf4FxQB8WngQIojBReU2t4BjAUOAh4CbgCIiK3AB4CLJR0BzKYIiksBJL1d0rN19Kmsns/L+qGBje6A7VoiYkgXk/eh+BVbthnYt3NDSQMoDkWdHxEvSercpGw6cEkd3TwD+FJEPJHW9X8pDmf9GiAiPtrFvLltGNm5YURskXQ38E+SPgkcSfGl3t65raRRFHs3f1/HdgD8R0Q8nZbxY2BDRDycxm8FJpb6M7e0vv8HbJK0f0RsjohHJV0C3EqxNzI+Iral+X5CcWisO2r+vKx/8p6E9aXnKH65l+1HcWiks48CyyLinq4WmPZaXgfcUkc/DgLWlMafpPjBVMtx8nq2AeD9wCHAWuAqil/vbeUG6fj8ncCVEXFjDX0oe7o0/PsK4/ukdQyQdJmkX0r6LcWhKij2ODrMozh0tzAiVtXZj5x6Py/rZxwS1h17lobr+YW5AjimY0TSmyjOD/yiQtuJwHslPSXpKeDPgH+X9JVO7ZqBb0fEc3X0o43ii7vDIcCLvPoLNmcF8CZJ5b2fY+h0Yr1DRDwZEadHxPCIOJ7i5O39HdPTifk7gQURcWkd21CvvwamUhxm258iDODVh8KuBG4HTu3ikGG96vq8rP9xSFh3nJt+mY6j+DLfV9IeNcx3A/AXkk6StDdwMcUXfKVflR8EjgDGpVcL8FmKq2MAkDQYOIvi5PmrSFqaDqlUcj1woaQ3SdqH4oT6NyLixWobEBG/oDjJO0fSnpLeC/wp8K1K7SUdIWlfSYMkfQCYBHwhTdsPWATcHRGzK8x7sqSeupf/vhQnkJ8B9qLY5vK6zgGOo/jcLwDmpc+mKkmvkbQnsEcxqj0lDYL6Py/rfxwS1h17UVwZ9F/AZyh+zZ8CkP5m4aRKM0XECuAjFGGxgeKL6+Xj/+lvHz6d2j4bEU91vChOcP82IsrHt8+kOL59V4XVjaa4QqeS6yku2byL4vLU5ylOZnf042uSujpZPo3ihPom4DLgfRHRnuZ9v6Tyr+RTgdWp7UeAyR1tgfcCb6MI3fLffLyhtA1dHm6rw3yKw2q/Bh4D7u2YkNb3JWB6RDwXEV+nCOUvpuknSepqT+0dFIe2FgJvSMN3lqZnPy/r/xThhw5Z7dIv27ER0drovuSkk8DfjIgTGt2XHSHpGortWNTovtjuyyFhddkZQsLMeo4PN5mZWZb3JMzMLMt7EmZmlrXT/sX1gQceGGPGjGl0N8zMdhoPPvjgbyKirpsr7rQhMWbMGFpaWhrdDTOznYakJ+udx4ebzMwsyyFhZmZZDgkzM8tySJiZWZZDwszMshwSZmaW5ZAwM7Msh4SZmWU5JMzMLGu3DIkRo96ApD5/jRj1huqdMzPrR3ba23LsiKd+vZY3fur2Pl/vk5ef3ufrNDPbEVX3JCQdJumR0uu3ki6UNEzSYkmr0vvQ1F6SrpDUKmmZpGNLy2pO7VdJai7Vj5O0PM1zhSRV6ouZmfWtqiEREY9HxLiIGEfxoPTngVuB2cCSiBgLLEnjAFOAsek1E7gKQNIwYA5wPDCe4sHoQ9M8V6W2HfNN7pGtMzOzHVLvOYmJwC8j4klgKjAv1edRPJSeVJ8fhXuBIZJGUDwQfnFEbIyITcBiYHKatl9E3BPFE5Dml5ZlZmYNVG9ITANuTMMHR8R6gPR+UKqPBNaW5mlLta7qbRXq25E0U1KLpJb29vY6u25mZvWqOSQkDQLOAL5ZrWmFWnSjvn0x4uqIaIqIpuHD63puhpmZdUM9exJTgIci4uk0/nQ6VER635DqbcDo0nyjgHVV6qMq1M3MrMHqCYmzeeVQE8ACoOMKpWbgtlJ9errKaQKwOR2OWgRMkjQ0nbCeBCxK07ZImpCuappeWpaZmTVQTX8nIWkv4N3A35bKlwE3S5oBrAHOSvWFwGlAK8WVUOcCRMRGSZ8DHkjtLo6IjWn4POA6YDBwR3qZmVmD1RQSEfE8cECn2jMUVzt1bhvArMxy5gJzK9RbgKNr6YuZmfWd3fK2HGZmVhuHhJmZZTkkzMwsyyFhZmZZDgkzM8tySJiZWZZDwszMshwSZmaW5ZAwM7Msh4SZmWU5JMzMLMshYWZmWQ4JMzPLckiYmVmWQ8LMzLIcEmZmluWQMDOzLIeEmZllOSTMzCzLIWFmZlk1hYSkIZJukfRzSSslnSBpmKTFklal96GprSRdIalV0jJJx5aW05zar5LUXKofJ2l5mucKSer5TTUzs3rVuifxZeB7EXE4cAywEpgNLImIscCSNA4wBRibXjOBqwAkDQPmAMcD44E5HcGS2swszTd5xzbLzMx6QtWQkLQf8A7gWoCI2BoRzwJTgXmp2TzgzDQ8FZgfhXuBIZJGAKcCiyNiY0RsAhYDk9O0/SLinogIYH5pWWZm1kC17Em8CWgH/lvSw5KukbQ3cHBErAdI7wel9iOBtaX521Ktq3pbhfp2JM2U1CKppb29vYaum5nZjqglJAYCxwJXRcRbgd/xyqGlSiqdT4hu1LcvRlwdEU0R0TR8+PCue21mZjuslpBoA9oi4r40fgtFaDydDhWR3jeU2o8uzT8KWFelPqpC3czMGqxqSETEU8BaSYel0kTgMWAB0HGFUjNwWxpeAExPVzlNADanw1GLgEmShqYT1pOARWnaFkkT0lVN00vLMjOzBhpYY7vzgRskDQJWA+dSBMzNkmYAa4CzUtuFwGlAK/B8aktEbJT0OeCB1O7iiNiYhs8DrgMGA3ekl5mZNVhNIRERjwBNFSZNrNA2gFmZ5cwF5laotwBH19IXMzPrO/6LazMzy3JImJlZlkPCzMyyHBJmZpblkDAzsyyHhJmZZTkkzMwsyyFhZmZZDgkzM8tySJiZWZZDwszMshwSZmaW5ZAwM7Msh4SZmWU5JMzMLMshYWZmWQ4JMzPLckiYmVmWQ8LMzLIcEmZmllVTSEh6QtJySY9Iakm1YZIWS1qV3oemuiRdIalV0jJJx5aW05zar5LUXKofl5bfmuZVT2+omZnVr549iXdGxLiIaErjs4ElETEWWJLGAaYAY9NrJnAVFKECzAGOB8YDczqCJbWZWZpvcre3yMzMesyOHG6aCsxLw/OAM0v1+VG4FxgiaQRwKrA4IjZGxCZgMTA5TdsvIu6JiADml5ZlZmYNVGtIBHCnpAclzUy1gyNiPUB6PyjVRwJrS/O2pVpX9bYK9e1ImimpRVJLe3t7jV03M7PuGlhjuxMjYp2kg4DFkn7eRdtK5xOiG/XtixFXA1cDNDU1VWxjZmY9p6Y9iYhYl943ALdSnFN4Oh0qIr1vSM3bgNGl2UcB66rUR1Wom5lZg1UNCUl7S9q3YxiYBDwKLAA6rlBqBm5LwwuA6ekqpwnA5nQ4ahEwSdLQdMJ6ErAoTdsiaUK6qml6aVlmZtZAtRxuOhi4NV2VOhD4ekR8T9IDwM2SZgBrgLNS+4XAaUAr8DxwLkBEbJT0OeCB1O7iiNiYhs8DrgMGA3ekl5mZNVjVkIiI1cAxFerPABMr1AOYlVnWXGBuhXoLcHQN/TUzsz7kv7g2M7Msh4SZmWU5JMzMLMshYWZmWQ4JMzPLckiYmVmWQ8LMzLIcEmZmluWQMDOzLIeEmZllOSTMzCzLIWFmZlkOCTMzy3JImJlZlkPCzMyyHBJmZpblkDAzsyyHhJmZZTkkzMwsq+aQkDRA0sOSbk/jh0i6T9IqSd+QNCjVX5vGW9P0MaVlXJTqj0s6tVSfnGqtkmb33OaZmdmOqGdP4uPAytL45cAXI2IssAmYkeozgE0R8Rbgi6kdko4EpgFHAZOBK1PwDAC+CkwBjgTOTm3NzKzBagoJSaOA9wDXpHEBpwC3pCbzgDPT8NQ0Tpo+MbWfCtwUES9ExK+AVmB8erVGxOqI2ArclNqamVmD1bon8SXgH4GX0vgBwLMR8WIabwNGpuGRwFqANH1zav9yvdM8ubqZmTVY1ZCQdDqwISIeLJcrNI0q0+qtV+rLTEktklra29u76LWZmfWEWvYkTgTOkPQExaGgUyj2LIZIGpjajALWpeE2YDRAmr4/sLFc7zRPrr6diLg6Ipoiomn48OE1dN3MzHZE1ZCIiIsiYlREjKE48fyDiHg/cBfwvtSsGbgtDS9I46TpP4iISPVp6eqnQ4CxwP3AA8DYdLXUoLSOBT2ydWZmtkMGVm+S9SngJkmXAA8D16b6tcD1klop9iCmAUTECkk3A48BLwKzImIbgKSPAYuAAcDciFixA/0yM7MeUldIRMRSYGkaXk1xZVLnNn8AzsrMfylwaYX6QmBhPX0xM7Pe57+4NjOzLIeEmZllOSTMzCzLIWFmZlkOCTMzy3JImJlZlkPCzMyyHBJmZpblkDAzsyyHhJmZZTkkzMwsyyFhZmZZDgkzM8tySJiZWZZDwszMshwSZmaW5ZAwM7Msh4SZmWU5JMzMLMshYWZmWVVDQtKeku6X9DNJKyR9NtUPkXSfpFWSviFpUKq/No23puljSsu6KNUfl3RqqT451Volze75zTQzs+6oZU/iBeCUiDgGGAdMljQBuBz4YkSMBTYBM1L7GcCmiHgL8MXUDklHAtOAo4DJwJWSBkgaAHwVmAIcCZyd2pqZWYNVDYkoPJdG90ivAE4Bbkn1ecCZaXhqGidNnyhJqX5TRLwQEb8CWoHx6dUaEasjYitwU2prZmYNVtM5ifSL/xFgA7AY+CXwbES8mJq0ASPT8EhgLUCavhk4oFzvNE+uXqkfMyW1SGppb2+vpetmZrYDagqJiNgWEeOAURS//I+o1Cy9KzOt3nqlflwdEU0R0TR8+PDqHTczsx1S19VNEfEssBSYAAyRNDBNGgWsS8NtwGiANH1/YGO53mmeXN3MzBqslqubhksakoYHA+8CVgJ3Ae9LzZqB29LwgjROmv6DiIhUn5aufjoEGAvcDzwAjE1XSw2iOLm9oCc2zszMdszA6k0YAcxLVyG9Brg5Im6X9Bhwk6RLgIeBa1P7a4HrJbVS7EFMA4iIFZJuBh4DXgRmRcQ2AEkfAxYBA4C5EbGix7bQzMy6rWpIRMQy4K0V6qspzk90rv8BOCuzrEuBSyvUFwILa+ivmZn1If/FtZmZZTkkzMwsyyFhZmZZDgkzM8tySJiZWZZDwszMshwSZmaW5ZAwM7Msh4SZmWU5JMzMLMshYWZmWQ4JMzPLckiYmVmWQ8LMzLIcEmZmluWQMDOzLIeEmZllOSTMzCzLIWFmZlkOCTMzy6oaEpJGS7pL0kpJKyR9PNWHSVosaVV6H5rqknSFpFZJyyQdW1pWc2q/SlJzqX6cpOVpniskqTc21szM6lPLnsSLwD9ExBHABGCWpCOB2cCSiBgLLEnjAFOAsek1E7gKilAB5gDHA+OBOR3BktrMLM03ecc3zczMdlTVkIiI9RHxUBreAqwERgJTgXmp2TzgzDQ8FZgfhXuBIZJGAKcCiyNiY0RsAhYDk9O0/SLinogIYH5pWWZm1kB1nZOQNAZ4K3AfcHBErIciSICDUrORwNrSbG2p1lW9rUK90vpnSmqR1NLe3l5P183MrBtqDglJ+wDfAi6MiN921bRCLbpR374YcXVENEVE0/Dhw6t12czMdlBNISFpD4qAuCEivp3KT6dDRaT3DaneBowuzT4KWFelPqpC3czMGqyWq5sEXAusjIgvlCYtADquUGoGbivVp6ernCYAm9PhqEXAJElD0wnrScCiNG2LpAlpXdNLyzIzswYaWEObE4FzgOWSHkm1TwOXATdLmgGsAc5K0xYCpwGtwPPAuQARsVHS54AHUruLI2JjGj4PuA4YDNyRXmZm1mBVQyIifkLl8wYAEyu0D2BWZllzgbkV6i3A0dX6YmZmfct/cW1mZlkOCTMzy3JImJlZlkPCzMyyHBJmZpblkDAzsyyHhJmZZdXyx3TWUwbsQaMelfG6kaNZ37amIes2s52XQ6Ivbfsjb/zU7Q1Z9ZOXn96Q9ZrZzs2Hm8zMLMshYWZmWQ4JMzPLckiYmVmWQ8LMzLIcEmZmluWQMDOzLIeEmZllOSTMzCzLIWFmZlkOCTMzy6oaEpLmStog6dFSbZikxZJWpfehqS5JV0hqlbRM0rGleZpT+1WSmkv14yQtT/NcoUbdAc/MzLZTy57EdcDkTrXZwJKIGAssSeMAU4Cx6TUTuAqKUAHmAMcD44E5HcGS2swszdd5XWZm1iBVQyIifgRs7FSeCsxLw/OAM0v1+VG4FxgiaQRwKrA4IjZGxCZgMTA5TdsvIu6JiADml5ZlZmYN1t1zEgdHxHqA9H5Qqo8E1pbataVaV/W2CvWKJM2U1CKppb29vZtdNzOzWvX0ietK5xOiG/WKIuLqiGiKiKbhw4d3s4tmZlar7obE0+lQEel9Q6q3AaNL7UYB66rUR1Wom5lZP9DdkFgAdFyh1AzcVqpPT1c5TQA2p8NRi4BJkoamE9aTgEVp2hZJE9JVTdNLyzIzswar+vhSSTcCJwMHSmqjuErpMuBmSTOANcBZqflC4DSgFXgeOBcgIjZK+hzwQGp3cUR0nAw/j+IKqsHAHellZmb9QNWQiIizM5MmVmgbwKzMcuYCcyvUW4Cjq/XDdtCAPWjEn6C8buRo1ret6fP1mlnPqBoStovY9kfe+Knb+3y1T15+ep+v08x6jm/LYWZmWQ4JMzPLckiYmVmWQ8LMzLIcEmZmluWQMDOzLIeEmZllOSTMzCzLIWFmZlkOCTMzy3JImJlZlkPCzMyyHBJmZpblkDAzsyzfKtx6V4OeYwF+loVZT3BIWO9q0HMswM+yMOsJPtxkZmZZDgkzM8tySJiZWVa/CQlJkyU9LqlV0uxG98d2AemkeV+/Rox6Q6O33KzH9IsT15IGAF8F3g20AQ9IWhARjzW2Z7ZTa9BJc58wt11JvwgJYDzQGhGrASTdBEwFHBK282nQZb8DBu3Jtq1/6PP1gi833pUpIhrdByS9D5gcER9O4+cAx0fExzq1mwnMTKOHAY/3aUcLBwK/acB6G8nbvHvwNu/6DouIfeuZob/sSVT62bVdekXE1cDVvd+dPEktEdHUyD70NW/z7sHbvOuT1FLvPP3lxHUbMLo0PgpY16C+mJlZ0l9C4gFgrKRDJA0CpgELGtwnM7PdXr843BQRL0r6GLAIGADMjYgVDe5WTkMPdzWIt3n34G3e9dW9vf3ixLWZmfVP/eVwk5mZ9UMOCTMzy3JI1GF3unWIpNGS7pK0UtIKSR9vdJ/6iqQBkh6W1Jh7nPcxSUMk3SLp5+nf+4RG96m3Sfq79P/6UUk3Stqz0X3qaZLmStog6dFSbZikxZJWpfeh1ZbjkKhR6dYhU4AjgbMlHdnYXvWqF4F/iIgjgAnArF18e8s+DqxsdCf60JeB70XE4cAx7OLbLmkkcAHQFBFHU1wsM62xveoV1wGTO9VmA0siYiywJI13ySFRu5dvHRIRW4GOW4fskiJifUQ8lIa3UHxxjGxsr3qfpFHAe4BrGt2XviBpP+AdwLUAEbE1Ip5tbK/6xEBgsKSBwF7sgn+XFRE/AjZ2Kk8F5qXhecCZ1ZbjkKjdSGBtabyN3eBLE0DSGOCtwH2N7Umf+BLwj8BLje5IH3kT0A78dzrEdo2kvRvdqd4UEb8G/g1YA6wHNkfEnY3tVZ85OCLWQ/FDEDio2gwOidrVdOuQXY2kfYBvARdGxG8b3Z/eJOl0YENEPNjovvShgcCxwFUR8Vbgd9RwCGJnlo7DTwUOAV4P7C3pA43tVf/lkKjdbnfrEEl7UATEDRHx7Ub3pw+cCJwh6QmKw4mnSPqfxnap17UBbRHRsZd4C0Vo7MreBfwqItoj4o/At4E/a3Cf+srTkkYApPcN1WZwSNRut7p1iIp7XV8LrIyILzS6P30hIi6KiFERMYbi3/cHEbFL/8KMiKeAtZIOS6WJ7Pq36F8DTJC0V/p/PpFd/GR9yQKgOQ03A7dVm6Ff3JZjZ7CT3TqkJ5wInAMsl/RIqn06IhY2sE/WO84Hbkg/flYD5za4P70qIu6TdAvwEMVVfA+zC96eQ9KNwMnAgZLagDnAZcDNkmZQhOVZVZfj23KYmVmODzeZmVmWQ8LMzLIcEmZmluWQMDOzLIeEmZllOSSsx0jaJumRdGfN70oa0kvr+Z6kkekWEt266aCk16fLIHuqT2dK+kwaHi7pvnSbi5N6ah07Kt3t9aN9sJ4/kXRdb6/H+oYvgbUeI+m5iNgnDc8DfhERl/bwOgYDP4yI8T253B0l6afAGRHxG0nTgCkR0VxtvtL8AyJiW+/18OV7cN2e7nzaqyR9H/hQRKzp7XVZ7/KehPWWe0g3QJR0cvnZDJK+IumDafgJSZ+V9JCk5ZIOT/U/T3slj6Rf5Pum2U8GlqY2SyU1peHnJF0q6WeS7pV0cKpfJ+kKST+VtFrS+1J9TMd99iV9UNK30x7KKkn/UurrDEm/SOv6L0lf6byhkg4FXkgBMQ74F+C01PfBks5O2/aopMtL8z0n6WJJ9wEndFrmuLQdyyTd2nHf/9SPyyXdn/p1UqoPkPSvkh5I8/xthX+Ty4A3p379a5rvk6V5Plta/3ckPajimQszO/X58jTt+5LGpz6tlnRGaV3fZde8/fZuxyFhPU7FszcmUvttS34TEccCVwGfSLVPALMiYhxwEvD7VJ8CfK/CMvYG7o2IY4AfAX9TmjYCeDtwOsUXZSXjgL8C/gT4KxUPXXo98E8Uz9N4N3B4Zt4TKf56l4h4BPgM8I3U96HA5cApaR1vk9Rxe+a9gUcj4viI+EmnZc4HPhURfwosp/hr2Q4D057UhaX6DIq7mb4NeBvwN5IO6bTM2cAvI2JcRHxS0iRgLMVt8McBx0l6R2r7oYg4DmgCLpB0QKnPS9O0LcAl6bN5L3BxaV0tFP9utpNzSFhPGpxu4fEMMAxYXON8HTcPfBAYk4bvBr4g6QJgSES8mOonAp2/UAG2Ah17K+XlAHwnIl6KiMeAgzN9WBIRmyPiDxT3LnojxZfnDyNiY7oR3Dcz846guN12JW+j+FJtT9twA8XzGwC2UdxA8VUk7U+xzT9MpXmleaDy5zUJmJ4+//uAAygCoCuT0uthipA7vDTPBZJ+BtxLcWPLjvpWXgnp5RSfzx/TcEdfoLhx3OurrN92Ar53k/Wk30fEuPQldzswC7iC4v445R8knR8V+UJ630b6PxkRl0n6X+A04F5J76L4glqbHvrU2R/jlRNsLy+n0/Kh8i3fO7fpmD/XtrPfA/tnpnW1jD908zzEdp9XWs/5EbGojuUI+OeI+M9XFaWTKe6UekJEPC9pKa/8m5U/55c6+hIRL6l4gE+HPXll7892Yt6TsB4XEZspHg/5CRW3G38SOFLSa1OATKy2DElvjojlEXE5xaGLw8kfauot9wN/Lmlo+gL8y0y7lcBbMtPuS8s4MB2GOxv4YaYt8PLnt6l0ZdQ51eahuPHkeenzRtKh2v7hQVuAfTvN8yEVzwxBxRVjB1EE3qYUEIdTHG6r16HAo1VbWb/nPQnrFRHxcDpcMS0irpd0M7AMWEVxeKOaCyW9k+LX8mPAHRTPOji/t/rcWUT8WtLnKb7o16V+bK7Q9EfAv0tS6Vd2xzLWS7oIuIvil/vCiKh6e2aK2zh/TdJe1HZn1msoDvc8JEkUh79e9WjKiHhG0t3phP0d6bzEEcA9xSw8B3yAIog/ImkZ8DjFIad6vRP4327MZ/2ML4G1nYKk1wJ3R0RTH693n4h4Lu1J3Epxi/hbK7T7MvDdiPh+X/avP0r/Vj8E3l46l2Q7KYeEWRck/RvF8fk9gTuBj3feW0jtDgaOj4hd9kFUtZI0FhgZEUsb3RfbcQ4JMzPL8olrMzPLckiYmVmWQ8LMzLIcEmZmluWQMDOzrP8PWOaRJE9Q/JIAAAAASUVORK5CYII=\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?"
]
}
],
@@ -317,7 +839,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.7.2"
+ "version": "3.7.6"
}
},
"nbformat": 4,