Skip to content

Instantly share code, notes, and snippets.

@nealcaren
Last active December 23, 2015 20:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nealcaren/6689516 to your computer and use it in GitHub Desktop.
Save nealcaren/6689516 to your computer and use it in GitHub Desktop.
NCAA FIeld Hockey Data Scraper and Prediction Machine
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "Field Hockey"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Python code for predicting NCAA field hockey games\n",
"----------\n",
"Neal Caren - University of North Carolina, Chapel Hill\n",
"[mail](mailto:neal.caren@unc.edu)\n",
"[web](http://nealcaren.web.unc.edu)\n",
"[twitter](http://twitter.com/HaphazardSoc)\n",
"[scholar](http://scholar.google.com/citations?user=cy0u16kAAAAJ&hl=en)\n",
"\n",
"[Current predictions](http://www.unc.edu/~ncaren/fhprediction.html) \n",
"\n",
"This code follows my standard workflow for collecting and analyzing data from the web, so I \n",
"think it might be useful, even if you don't care about sports rankings or field hockey.\n",
"\n",
"I begin by gathering a list of all the web pages I want to scrape with the `get_teams` function. \n",
"The next pair of functions, `get_schedule` and `read_table_row' scrape that have the data I'm interested in. \n",
"In this case, I'm interested in all the played and scheduled games, and looking to grab the date, opponent, and score. \n",
"For unknown reasons, schools sometimes go by different names, so I have to do some name cleaning. The last step, \n",
"begining with `generate_skill`, does a little bit of analysis. Here, I'm simply computing a power ranking that is the average victory margin, \n",
"adjusting for home field advantage and opponent's average victory margin. I use a similar method to compute total points scored. \n",
"Finally, I estimate some predicted values for the games that haven't been played yet. If I was doing anything fancier, \n",
"I would use Pandas and/or scikit-learn or export the data.\n"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import requests\n",
"import re\n",
"import csv\n",
"import numpy as np\n",
"\n",
"from time import sleep"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def get_teams():\n",
" #Reads FieldHockeyCorner and grabs all the NCAA Division 1 team names and abrreviations\n",
" url = 'http://www.fieldhockeycorner.com/scores.php?div=1'\n",
" page = requests.get(url)\n",
" teams = re.findall(\"tcode=(.*?)&div=1'>(.*?)<\",page.text)\n",
" return teams\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def get_schedule(team):\n",
" #Grabs the schedule for a specific team\n",
" #Includes games played and to be played\n",
" sleep(.5)\n",
" print 'Gettings schedule for', team[1]\n",
" url = 'http://www.fieldhockeycorner.com/scores.php?action=schedule&tcode=%s&div=1' % team[0]\n",
" page = requests.get(url)\n",
" table = re.findall('<tr><td>(.*?)<\\/td><td>(.*?)<\\/td><td>(.*?)<\\/td><td>(.*?)<\\/td><\\/tr>',page.text)\n",
" table = [ read_table_row(row, team[1]) for row in table]\n",
" return table\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def read_table_row(row, team):\n",
" #Decodes a row of the table from Fieldhockey corner\n",
" try:\n",
" score = [item for item in row[2].split() if '-' in item][0]\n",
" own_score = score.split('-')[0]\n",
" other_score = score.split('-')[1]\n",
" except:\n",
" other_score = '.'\n",
" own_score = '.'\n",
" \n",
" if 'vs. ' in row[1]:\n",
" location = 'Neutral'\n",
" elif '<b>' in row[1]:\n",
" location = 'Home'\n",
" elif 'at' in row[1]:\n",
" location = 'Away'\n",
" else:\n",
" location = 'Other'\n",
" return {'team' : team,\n",
" 'date' : row[0],\n",
" 'opponent' : row[1].replace('vs. ','').replace('</b>','').replace('<b>','').replace('at ',''),\n",
" 'notes' : row[3],\n",
" 'location' : location,\n",
" 'own_score': own_score,\n",
" 'other_score' : other_score\n",
" }\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#grab the teams and their schedules\n",
"teams = get_teams()\n",
"schedules = [ get_schedule(team) for team in teams]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Gettings schedule for Albany\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Delaware\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Longwood\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Pacific\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Syracuse\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" American\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Drexel\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Louisville\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Penn\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Temple\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Appalachian St.\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Duke\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Maine\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Penn State\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Towson\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Ball State\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Fairfield\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Maryland\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Princeton\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" UC Davis\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Boston C.\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Georgetown\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Massachusetts\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Providence\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" UMass-Lowell\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Boston U.\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Harvard\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Miami\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Quinnipiac\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Vermont\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Brown\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Hofstra\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Michigan\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Radford\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Villanova\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Bryant\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Holy Cross\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Michigan State\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Richmond\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Virginia\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Bucknell\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Indiana\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Missouri State\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Rider\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" VCU\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" California\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Iowa\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Monmouth\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Robert Morris\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Wake Forest\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Central Michigan\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" James Madison\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" New Hampshire\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Rutgers\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" William & Mary\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Colgate\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Kent State\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" North Carolina\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Sacred Heart\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Yale\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Columbia\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" La Salle\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Northeastern\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Saint Francis\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Connecticut\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Lafayette\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Northwestern\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Saint Joseph's\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Cornell\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Lehigh\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Ohio\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Saint Louis\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Dartmouth\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Liberty\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Ohio State\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Siena\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Davidson\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Lock Haven\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Old Dominion\n",
"Gettings schedule for"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
" Stanford\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Flatten the list so it a list of games\n",
"games = [item for sublist in schedules for item in sublist]"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Split into played and unplayed\n",
"played_games = [game for game in games if game['own_score']!='.']\n",
"unplayed_games = [game for game in games if game['own_score']=='.']"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#Because some names are listed in mulitple ways\n",
"name_clean = {'Boston C.': 'Boston College',\n",
" 'Boston U.': 'Boston University',\n",
" 'Vcu' : 'Virginia Commonwealth',\n",
" 'Appalachian St.' : 'Appalachian State',\n",
" 'Uc Davis' : 'UC Davis'}"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 8
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def generate_skill(games, n=50):\n",
" #Ranking algorithm. Average winning margin adjusted for opponents winning margin\n",
" #N is the number of times to iterate through. Seems to converge after 10 or so loops\n",
" \n",
" skill = {}\n",
" for x in range(0, n):\n",
" team_skill_list = {}\n",
" for game in games:\n",
" #clean up the team names\n",
" team = name_clean.get(game['team'].title(),game['team'].title())\n",
" opponent = name_clean.get(game['opponent'].title(),game['opponent'].title())\n",
" \n",
" #Hard coded Home Field Advantage at .7, which was the figure from 2012\n",
" if game['location'] == 'Home':\n",
" hfa = .7\n",
" else:\n",
" hfa = 0\n",
" \n",
" #figure out how unexpected the margin of victory was\n",
" expected_margin = skill.get(team,0) - skill.get(opponent,0) + hfa \n",
" observed_margin = int(game['own_score']) - int(game['other_score'])\n",
" difference = observed_margin - expected_margin\n",
" \n",
" #Add the unexpected portion to a list by team\n",
" try:\n",
" team_skill_list[team].append(difference)\n",
" except:\n",
" team_skill_list[team] = [observed_margin - expected_margin]\n",
"\n",
" #New skill is old skill plus average of the new unexpected portion\n",
" skill = {team: np.mean(team_skill_list[team]) + skill.get(team,0) for team in team_skill_list}\n",
"\n",
" #center the skills to prevent drift\n",
" mean = np.mean([skill[team] for team in skill])\n",
" skill = {team: skill[team] - mean for team in skill}\n",
" return skill"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"skills = generate_skill(played_games)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 10
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"#take a look at the top teams\n",
"for team in sorted(skills, key=skills.get, reverse=True)[:5]:\n",
" print team,skills[team]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Maryland 5.93977027965\n",
"North Carolina 5.16134861747\n",
"Virginia 3.81517327634\n",
"Connecticut 3.66998671713\n",
"Iowa 3.35718763212\n"
]
}
],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def generate_total(games, n=20):\n",
" #Same function as above, expcept for total points score rather than margin\n",
" #Shoudl probably be combined with above\n",
" total = {}\n",
" for x in range(0, n):\n",
" team_total_list = {}\n",
" for game in games:\n",
" \n",
" team = name_clean.get(game['team'].title(),game['team'].title())\n",
" opponent = name_clean.get(game['opponent'].title(),game['opponent'].title())\n",
" \n",
" \n",
" expected_total = total.get(team,0) + total.get(opponent,0) + 4.7 \n",
" observed_total = int(game['own_score']) + int(game['other_score'])\n",
" difference = observed_total - expected_total\n",
" \n",
" try:\n",
" team_total_list[team].append(difference)\n",
" except:\n",
" team_total_list[team] = [difference]\n",
"\n",
" #New total is old total plus new average\n",
" total = {team: np.mean(team_total_list[team]) + total.get(team,0) for team in team_total_list}\n",
" return total"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"totals = generate_total(played_games)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for team in sorted(totals, key=totals.get, reverse=True)[:10]:\n",
" print team,totals[team]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Kent State 2.64308192784\n",
"Dartmouth 2.41186253797\n",
"Maryland 2.3897954595\n",
"Saint Louis 1.99132275916\n",
"Penn 1.74421499118\n",
"North Carolina 1.54463283301\n",
"Vermont 1.4099056861\n",
"Boston College 1.35897993364\n",
"Appalachian State 1.15298955323\n",
"Longwood 1.07484246491\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def make_prediction(games,skill,total):\n",
" # for unplayed games, come up with a prediction based on location, \n",
" # and who is playing\n",
" predictions = {}\n",
" for game in games:\n",
" team = name_clean.get(game['team'].title(),game['team'].title())\n",
" opponent = name_clean.get(game['opponent'].title(),game['opponent'].title())\n",
" \n",
" total_predict = 4.7 + total.get(team,0) + total.get(opponent,0)\n",
" \n",
" if game['location']=='Home':\n",
" hfa = .7\n",
" modifier = \"at\"\n",
" else: \n",
" hfa = 0\n",
" modifier =\"vs\"\n",
" \n",
" #Quick hack to sort by date\n",
" date = game['date']\n",
" day = int(date.split()[1])\n",
" if 'Sep. ' in date:\n",
" day = day + 900\n",
" elif 'Oct. ' in date:\n",
" day = day + 1000\n",
" elif 'Nov. ' in date:\n",
" day = day + 1100\n",
" elif 'Dec. ' in date:\n",
" day = day + 1200 \n",
" \n",
" #Only print out away games to avoid duplication\n",
" if game['location']!='Away':\n",
" expected_margin = skill.get(team,0) - skill.get(opponent,0) + hfa\n",
"\n",
" \n",
" expected_margin = round(expected_margin * 2,0)/2\n",
" \n",
" total_predict = round(total_predict*2,0)/2\n",
" \n",
" #fix for cases where margin is greater than difference:\n",
" if expected_margin > total_predict:\n",
" expected_margin = total_predict\n",
" \n",
" # fix for -0 margin\n",
" row = [date,'%s %s %s' % (opponent,modifier,team),\"%.1f\" % -expected_margin,\"%.1f\" % total_predict]\n",
" try:\n",
" predictions[day].append(row)\n",
" except:\n",
" predictions[day] = [row]\n",
" \n",
" return predictions\n",
" \n",
" "
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 15
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"preds = make_prediction(unplayed_games,skills,totals)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 16
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for day in preds:\n",
" print ' '.join(preds[day][0])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Oct. 25 William & Mary at Drexel -3.0 4.0\n",
"Oct. 26 Fairfield at Albany -4.0 5.5\n",
"Oct. 27 Princeton at Albany -2.0 6.0\n",
"Oct. 28 Maine at Providence 1.0 4.0\n",
"Oct. 30 Villanova at Penn -5.0 5.5\n",
"Oct. 31 Stanford at California 1.5 1.5\n",
"Sep. 24 UC Davis at Miami -4.0 5.0\n",
"Sep. 25 Rider at Drexel -4.0 4.0\n",
"Sep. 26 Richmond at Longwood 3.0 4.5\n",
"Sep. 27 Sacred Heart at Albany -5.0 5.0\n",
"Sep. 28 Stanford vs Syracuse -0.5 3.0\n",
"Sep. 29 Stanford at Albany -1.0 4.5\n",
"Nov. 1 Delaware at Drexel -1.0 5.0\n",
"Nov. 2 North Carolina at Syracuse 1.5 6.0\n",
"Nov. 3 Villanova at Delaware -4.5 4.5\n",
"Nov. 9 Princeton at Penn -0.0 7.0\n",
"Nov. 10 Harvard at Columbia -2.5 4.0\n",
"Oct. 1 Bryant at Holy Cross 0.5 4.0\n",
"Oct. 2 Lafayette at Penn -1.5 6.0\n",
"Oct. 4 William & Mary at Delaware -2.5 5.0\n",
"Oct. 5 Virginia at Syracuse -0.0 4.5\n",
"Oct. 6 Virginia at Albany 0.5 5.5\n",
"Oct. 7 Missouri State at Iowa -3.0 3.0\n",
"Oct. 8 Hofstra at Maryland -7.5 7.5\n",
"Oct. 9 Liberty at Longwood 0.5 4.5\n",
"Oct. 10 Richmond at William & Mary 2.0 3.5\n",
"Oct. 11 Towson at Delaware -4.0 4.0\n",
"Oct. 12 Vermont at Albany -7.0 7.0\n",
"Oct. 13 Princeton at Delaware -1.0 6.0\n",
"Oct. 15 Holy Cross at Vermont -0.5 5.0\n",
"Oct. 16 Radford at Wake Forest -4.5 4.5\n",
"Oct. 17 Lafayette at Drexel -2.5 3.5\n",
"Oct. 18 New Hampshire at Albany -3.0 6.5\n",
"Oct. 19 Wheelock at American -3.0 4.5\n",
"Oct. 20 Radford at Longwood -2.0 5.5\n",
"Oct. 22 Central Michigan at Michigan State -1.0 5.0\n",
"Oct. 23 Ohio State at Ball State 3.0 3.5\n"
]
}
],
"prompt_number": 21
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Not shown: Ugly code that turns the predictions into an html table."
]
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment