Analyze and simulate NCAA march madness tournaments
Project description
Welcome to Bracketology!
The goal of bracketology is to speed up the analysis of NCAA march madness data and help develop algorithms for filling out brackets.
- Documentation:
- GitHub Repo:
- Issue Tracker:
- Backlog:
https://github.com/stahl085/bracketology/projects/1?fullscreen=true
- PyPI:
Before You Start
- Here are the main things you need to know:
The main parts of this package are the
Bracket
objects and simulator functions in thesimulators
moduleA Bracket is composed of
Team
andGame
objectsGame objects have two Team objects as attributes, and the round number
Teams have a name, seed, and dictionary for statistics
Simulator functions have 1 argument of type Game, and return the winning Team of that Game
Installation
Install from pip
pip install bracketology
Or download directly from PyPi
Getting Started
Import bracketology and create a bracket from last year.
from bracketology import Bracket, Game, Team
# Create a bracket object from 2019
year = 2019
b19 = Bracket(year)
Tutorial
Inspecting the Bracket Object
Here are three different ways you can inspect the Bracket.
Inspect teams in each region (dictionary of actual results)
Inspect actual results by round (dictionary)
Inspect simulated results by round (list of Team attributes)
Get Teams in each Region
Print out all the teams in each region. The regions attribute is a dictionary with the information of all the teams in each region.
>>> print(b19.regions)
{
'East': [{'Team': 'Duke', 'Seed': 1},
{'Team': 'Michigan St', 'Seed': 2},
{'Team': 'LSU', 'Seed': 3},
...],
'West': [{'Team': 'Gonzaga', 'Seed': 1},
{'Team': 'Michigan', 'Seed': 2},
{'Team': 'Texas Tech', 'Seed': 3},
...],
'Midwest': [{'Team': 'North Carolina', 'Seed': 1},
{'Team': 'Kentucky', 'Seed': 2},
{'Team': 'Houston', 'Seed': 3},
...],
'South': [{'Team': 'Virginia', 'Seed': 1},
{'Team': 'Tennessee', 'Seed': 2},
{'Team': 'Purdue', 'Seed': 3},
...]
}
Actual Results by Round
The result attribute will return a dictionary (similar to regions above) but will be broken out by which teams actually made it to each round. You can use it to inspect the real tournament results.
>>> print(b19.result.keys())
dict_keys(['first', 'second', 'sweet16', 'elite8', 'final4', 'championship', 'winner'])
>>> print(b19.result['final4'])
[{'Team': 'Michigan St', 'Seed': 2}, {'Team': 'Virginia', 'Seed': 1},
{'Team': 'Texas Tech', 'Seed': 3}, {'Team': 'Auburn', 'Seed': 5}]
>>> print(b19.result.get('winner'))
{'Team': 'Virginia', 'Seed': 1}
Simulation Results by Round
Print out all the teams that are simulated to make it to each round. The first round is filled out by default. This is a list of Team objects that are simulated to make it to each round. Right now round2 is an empty list because we have not simulated the bracket yet.
>>> print(b19.round1)
[<1 Duke>, <2 Michigan St>, <3 LSU>, ... , <1 Gonzaga>, <2 Michigan>, <3 Texas Tech>,
... , <1 North Carolina>, <2 Kentucky>, <3 Houston>, ... , <1 Virginia>, <2 Tennessee>, <3 Purdue>]
>>> print(b19.round2)
[]
Creating a Simulator Algorithm
A simulator function needs to take in a Game and Return a Team.
First we create some faux teams and games to test our simulator function on.
# Create teams
team1 = Team(name='Blue Mountain State',seed=1)
team2 = Team(name='School of Hard Knocks',seed=2)
​
# Create a game between the teams
game1 = Game(team1, team2, round_number=1)
Then we define the simulator function.
import random
def pick_a_random_team(the_game):
# Extract Teams from Game
team1 = the_game.top_team
team2 = the_game.bottom_team
​
# Randomly select a winner
if random.random() < 0.5:
winner = team1
else:
winner = team2
# Return the lucky team
return winner
Test the function out on a game.
>>> pick_a_random_team(game1)
<2 School of Hard Knocks>
Let’s run some simulations with our function!
# Initialize Simulation Parameters
BMS_wins = 0
HardKnocks_wins = 0
n_games = 1000
​
# Loop through a bunch of games
for i in range(n_games):
# Simulate the winner
winner = pick_a_random_team(game1)
# Increment win totals
if winner.seed == 1:
BMS_wins += 1
elif winner.seed == 2:
HardKnocks_wins += 1
else:
raise Exception("We have a tie??")
​
# Calculate total win percentage
BMS_win_pct = round(BMS_wins/n_games, 4) * 100
HardKnocks_win_pct = round(HardKnocks_wins/n_games, 4) * 100
​
# Print out results
print(f"Blue Mountain State Win Percentage: %{BMS_win_pct}")
print(f"School of Hard Knocks Win Percentage: %{HardKnocks_win_pct}")
Output:
Blue Mountain State Win Percentage: %50.9
School of Hard Knocks Win Percentage: %49.1
Evaluting Simulator Results
Let’s evaluate our simulator function on some actual brackets.
# Initialize simulation parameters
n_sims = 1000 # number of times to simulate through all years
total_sims = (n_sims * len(brackets))
scores = []
correct_games = []
# Loop through a plethora of brackets
for i in range(n_sims):
for bracket in brackets:
# Run the algorithm on the bracket
bracket.score(sim_func=pick_a_random_team, verbose=False)
# Save the scoring results in a list
scores.append(bracket.total_score)
correct_games.append(bracket.n_games_correct)
# Calculate the average across all simulations
avg_score = round(sum(scores) / total_sims)
avg_correct = round(sum(correct_games) / total_sims)
# Print result
print(f"Average number total score {avg_score}/192")
print(f"Average number of games guessed correctly {avg_correct}/64")
Output:
Average number total score 31/192
Average number of games guessed correctly 21/64
Easy, right!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file bracketology-0.0.99.tar.gz
.
File metadata
- Download URL: bracketology-0.0.99.tar.gz
- Upload date:
- Size: 29.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/2.0.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0.post20200210 requests-toolbelt/0.9.1 tqdm/4.42.1 CPython/3.7.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 211f151a7c1a1b7224797e3f35d33cd3a50d4a8f2789b8ea873da6e7abba4137 |
|
MD5 | e29b388ad9b7aeacbb77cc34afc995c3 |
|
BLAKE2b-256 | 9a966444ed4666a5cd5c7b7b18b963528e3df857c33f9cb4df09f99dd10a7df1 |