{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This kernel creates basic logistic regression models and provides a \n# mechanism to select attributes and check results against tournaments since 2013\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\n\n# To create the final sumissions once the round2 data has been updated, set this to true\nROUND2 = False\nDATA_PATH = '../input/google-cloud-ncaa-march-madness-2020-division-1-mens-tournament/'\nROUND1_PATH = DATA_PATH + \"MDataFiles_Stage1/\"\nROUND2_PATH = DATA_PATH + \"MDataFiles_Stage2/\"","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-output":false},"cell_type":"code","source":"if ROUND2:\n    tourney_cresults = pd.read_csv(ROUND2_PATH + 'MNCAATourneyCompactResults.csv')\nelse:\n    tourney_cresults = pd.read_csv(ROUND1_PATH + 'MNCAATourneyCompactResults.csv')\n    \ntourney_cresults = tourney_cresults.loc[tourney_cresults['Season'] >= 2003]\n\ntraining_set = pd.DataFrame()\ntraining_set['Result'] = np.random.randint(0,2,len(tourney_cresults.index))\ntraining_set['Season'] = tourney_cresults['Season'].values\ntraining_set['Team1'] = training_set['Result'].values * tourney_cresults['WTeamID'].values + (1-training_set['Result'].values) * tourney_cresults['LTeamID'].values \ntraining_set['Team2'] = (1-training_set['Result'].values) * tourney_cresults['WTeamID'].values + training_set['Result'].values * tourney_cresults['LTeamID'].values \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"78ac1ade5e1ff7d5cb8ddc4411d0101653fa6cba"},"cell_type":"code","source":"# Calculate Delta Seeds\nif ROUND2:\n    seeds = pd.read_csv(ROUND2_PATH + 'MNCAATourneySeeds.csv')\nelse:\n    seeds = pd.read_csv(ROUND1_PATH + 'MNCAATourneySeeds.csv')\n\nseeds['Seed'] =  pd.to_numeric(seeds['Seed'].str[1:3], downcast='integer',errors='coerce')\n\ndef delta_seed(row):\n    cond = (seeds['Season'] == row['Season'])\n    return seeds[cond & (seeds['TeamID'] == row['Team1'])]['Seed'].iloc[0] - seeds[cond & (seeds['TeamID'] == row['Team2'])]['Seed'].iloc[0]\n\ntraining_set['deltaSeed'] = training_set.apply(delta_seed,axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"270086789bdeedc0b92e9c05daacd48afdd5405e"},"cell_type":"code","source":"# Calculate Delta Ordinals\nif ROUND2:\n    mo = pd.read_csv(ROUND2_PATH + 'MMasseyOrdinals_thru_2019_day_128.csv')\nelse:\n    mo = pd.read_csv(ROUND1_PATH + 'MMasseyOrdinals.csv')\nmo = mo[(mo['RankingDayNum'] == 128) & (mo['Season'] >= 2003)] # See Note on MO\n\ndef delta_ord(row):\n    cond =  (mo['Season'] == row['Season'])\n    cond1 = (mo['TeamID'] == row['Team1']) & cond\n    cond2 = (mo['TeamID'] == row['Team2']) & cond\n    t1 = mo[cond1]['OrdinalRank'].mean()\n    t2 = mo[cond2]['OrdinalRank'].mean()\n    return  t1-t2\n\ntraining_set['deltaMO'] = training_set.apply(delta_ord,axis=1)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"87221422dd24857b4ce63aade714183735b63839"},"cell_type":"code","source":"# Calculate win pct\nif ROUND2:\n    season_dresults = pd.read_csv(ROUND2_PATH + 'MRegularSeasonDetailedResults.csv')\nelse:\n    season_dresults = pd.read_csv(ROUND1_PATH + 'MRegularSeasonDetailedResults.csv')\n\nrecord = pd.DataFrame({'wins': season_dresults.groupby(['Season','WTeamID']).size()}).reset_index();\nlosses = pd.DataFrame({'losses': season_dresults.groupby(['Season','LTeamID']).size()}).reset_index();\n\nrecord = record.merge(losses, how='outer', left_on=['Season','WTeamID'], right_on=['Season','LTeamID'])\nrecord = record.fillna(0)\nrecord['games'] = record['wins'] + record['losses']\n\ndef delta_winPct(row):\n    cond1 = (record['Season'] == row['Season']) & (record['WTeamID'] == row['Team1'])\n    cond2 = (record['Season'] == row['Season']) & (record['WTeamID'] == row['Team2'])\n    return (record[cond1]['wins']/record[cond1]['games']).mean() - (record[cond2]['wins']/record[cond2]['games']).mean()\n\ntraining_set['deltaWinPct'] = training_set.apply(delta_winPct,axis=1)\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"281b3ff8de250e02167c6723c790a1d5f2cbed8b"},"cell_type":"code","source":"dfW = season_dresults.groupby(['Season','WTeamID']).sum().reset_index()\ndfL = season_dresults.groupby(['Season','LTeamID']).sum().reset_index()\n\ndef get_points_for(row):\n    wcond = (dfW['Season'] == row['Season']) & (dfW['WTeamID'] == row['WTeamID']) \n    fld1 = 'WScore'\n    lcond = (dfL['Season'] == row['Season']) & (dfL['LTeamID'] == row['WTeamID']) \n    fld2 = 'LScore'\n    retVal = dfW[wcond][fld1].sum()\n    if len(dfL[lcond][fld2]) > 0:\n        retVal = retVal + dfL[lcond][fld2].sum() \n    return retVal\n\ndef get_points_against(row):\n    wcond = (dfW['Season'] == row['Season']) & (dfW['WTeamID'] == row['WTeamID']) \n    fld1 = 'LScore'\n    lcond = (dfL['Season'] == row['Season']) & (dfL['LTeamID'] == row['WTeamID']) \n    fld2 = 'WScore'\n    retVal = dfW[wcond][fld1].sum()\n    if len(dfL[lcond][fld2]) > 0:\n        retVal = retVal + dfL[lcond][fld2].sum() \n    return retVal\n\nrecord['PointsFor'] = record.apply(get_points_for, axis=1)\nrecord['PointsAgainst'] = record.apply(get_points_against, axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"480b72c0d60c4d049b764c6fd70a0a7e035426bc"},"cell_type":"code","source":"def get_remaining_stats(row, field):\n    wcond = (dfW['Season'] == row['Season']) & (dfW['WTeamID'] == row['WTeamID']) \n    fld1 = 'W' + field\n    lcond = (dfL['Season'] == row['Season']) & (dfL['LTeamID'] == row['WTeamID']) \n    fld2 = 'L'+ field\n    retVal = dfW[wcond][fld1].sum()\n    if len(dfL[lcond][fld2]) > 0:\n        retVal = retVal + dfL[lcond][fld2].sum()\n    return retVal\n\ncols = ['FGM','FGA','FGM3','FGA3','FTM','FTA','OR','DR','Ast','TO','Stl','Blk','PF']\n\nfor col in cols:\n    print(\"Processing\",col)\n    record[col] = record.apply(get_remaining_stats, args=(col,), axis=1)\n\n#record['FGprct'] = record['FGM'] / record['FGA']    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ce8952441201d0fdf48248ed979f9acaad94105f"},"cell_type":"code","source":"def delta_stat(row, field):\n    cond1 = (record['Season'] == row['Season']) & (record['WTeamID'] == row['Team1'])\n    cond2 = (record['Season'] == row['Season']) & (record['WTeamID'] == row['Team2'])\n    return (record[cond1][field]/record[cond1]['games']).mean() - (record[cond2][field]/record[cond2]['games']).mean()\n\ncols = ['PointsFor','PointsAgainst','FGM','FGA','FGM3','FGA3','FTM','FTA','OR','DR','Ast','TO','Stl','Blk','PF']\n\nfor col in cols:\n    print(\"Processing\",col)\n    training_set['delta' + col] = training_set.apply(delta_stat,args=(col,),axis=1)\n\ntraining_set.describe()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9458e08483d55ec9743c9a6ad5a13a6bd75509ca","scrolled":true},"cell_type":"code","source":"# Train a model on all of the data\nimport statsmodels.api as sm\n\n# Field descriptions:\n# deltaSeed: difference in team's seeds\n# deltaMO: difference in team's Massey Ordinals on day 128\n# deltaWinPct: difference in the team's winning percentage \n# deltaPointsFor: difference in the average points scored per game\n# deltaPointsAgainst: difference in the average points scored agains the teams\n# deltaFGM: difference in the field goals made per game\n# deltaFGA: difference in the field goals attempted per game\n# deltaFGM3: difference in 3 point fields goals made per game\n# deltaFGA3: difference in the 3 points fields goals attempted per game\n# deltaFTM: difference in free throws made per game\n# deltaFTA: difference in free throws attempted per game\n# deltaOR: difference in offence rebounds per game\n# deltaDR: difference in defensive rebounds per game\n# deltaAst: difference in assists per game\n# deltaTO: difference in turnovers per game\n# deltaStl: difference in steals per game\n# deltaBlk: difference in blocks per game\n# deltaPF: difference in personal fouls per game\n\n# You would probabaly want to select a subset of these attributes\ncols = ['deltaSeed','deltaMO', 'deltaWinPct','deltaPointsFor','deltaPointsAgainst','deltaFGM','deltaFGA','deltaFGM3','deltaFGA3','deltaFTM',\n        'deltaFTA','deltaOR','deltaDR','deltaAst','deltaTO','deltaStl','deltaBlk','deltaPF']\nX = training_set[cols]\ny = training_set['Result']\n\nlogit_model=sm.Logit(y,X)\nresult=logit_model.fit()\nprint(result.summary2())       \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a14da4d34515372c9c64879ae28e92f095f0e311"},"cell_type":"code","source":"# Stats from previous competitions\n\nwinner=[0.52951,0.438933,0.481309,0.438575,0.531942,0.41477]\ntop5=[0.54772,0.453872,0.519706,0.461073,0.549876,0.43148]\ntopprctvalues=[5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100]\ntopprctscores=[[0.55620,0.465207,0.536976,0.472893,0.576667,0.44963], # 5%\n               [0.56035,0.469617,0.543597,0.479488,0.581399,0.45727], # 10%\n               [0.56411,0.474137,0.550067,0.486432,0.586220,0.46183], # 15%\n               [0.56958,0.478107,0.556954,0.491655,0.590554,0.46712], # 20%\n               [0.57177,0.481519,0.563566,0.495595,0.594101,0.47227], # 25%\n               [0.57495,0.486253,0.569619,0.500194,0.597493,0.47829], # 30%\n               [0.57946,0.490536,0.577442,0.505821,0.601023,0.48427], # 35%\n               [0.58676,0.496779,0.582541,0.511053,0.603920,0.48811], # 40%\n               [0.59418,0.500862,0.585897,0.515844,0.608200,0.49368], # 45%\n               [0.59921,0.508830,0.589459,0.522958,0.613297,0.49527], # 50%\n               [0.60593,0.516735,0.594342,0.528533,0.621995,0.49841], # 55%\n               [0.61288,0.523082,0.607036,0.534732,0.631227,0.50357], # 60%\n               [0.61915,0.528358,0.627708,0.541466,0.645569,0.50897], # 65%\n               [0.62780,0.539478,0.646980,0.556034,0.664821,0.51455], # 70%\n               [0.65659,0.552809,0.682279,0.576019,0.688618,0.52350], # 75%\n               [0.67932,0.574223,0.764058,0.605337,0.705595,0.53903], # 80%\n               [0.73514,0.625012,0.865465,0.643514,0.776256,0.55532], # 85%\n               [0.98764,0.692878,0.865465,0.693147,1.071796,0.57683], # 90%\n               [1.59656,0.882637,1.045207,0.897480,1.204277,0.61180], # 95%\n               [19.18820,11.513103,9.092529,12.609623,18.092158,20.83339],] # 100%\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"90a16ea7dd5f29bf2d1276a0f9b7ec48e94b22b4"},"cell_type":"code","source":"# Run cross validation on model against tournaments in 2003-2018.  For the tournaments since 2014, the winning score\n# from the Kaggle tournament is displayed\n\n# TODO: Choose some columns to build the logistic regression models\ncols = ['deltaMO', 'deltaWinPct', 'deltaPointsAgainst']\n\n# TODO: Adjust winning probabilities by this percent for selected teams, based on your\nbiases = {\n    '1163':1.2, # U Conn\n    '1181':1.2, # Duke \n    '1437':1.2, # Villanova\n    '1314':1.2, # UNC\n}\n\nerrs = []\nfor year in range(2003,2020):\n    print(\"Evaluation on tournament year\",year)\n    Xtrain = training_set[training_set['Season'] != year][cols]\n    ytrain = training_set[training_set['Season'] != year]['Result']\n\n    logit_model=sm.Logit(ytrain,Xtrain)\n    result=logit_model.fit()\n\n    Xtest = training_set[training_set['Season'] == year][cols]\n    ytest = training_set[training_set['Season'] == year]['Result']\n    \n    pred = result.predict(Xtest)\n    for bias in biases:\n        pred.loc[(training_set['Season'] == year) & (training_set['Team1'] == int(bias))] = pred.loc[(training_set['Season'] == year) & (training_set['Team1'] == int(bias))] * biases[bias] \n        pred.loc[(training_set['Season'] == year) & (training_set['Team2'] == int(bias))] = pred.loc[(training_set['Season'] == year) & (training_set['Team2'] == int(bias))] / biases[bias] \n    \n    pred.loc[(pred >= 0.9999)] = 0.9999\n    pred.loc[(pred <= 0.0001)] = 0.0001\n\n    pred.loc[training_set[training_set['Season'] == year]['Result'] == 0] = 1 - pred.loc[training_set[training_set['Season'] == year]['Result'] == 0] \n    err = -np.log(pred).mean()\n\n    errs.append(err)\n\nprint(\"Mean log loss: \",np.mean(errs))\n\n\n\nprint(\"Log losses by season\")\nprint(\"--------------------\")\nprint(\"year\",\"your score\",sep=\"\\t\")\nyears1 = range(2003,2014)\nfor i in range(len(years1)):\n    print(years1[i], \"{0:.6f}\".format(errs[i]),sep=\"\\t\")\n    \nprint(\"Log losses by season\")\nprint(\"--------------------\")\nprint(\"year\",\"your score\",\"your result\",\"winning score\",sep=\"\\t\")    \nyears2 = range(2014,2020)\nfor i in range(len(years2)):\n    result = None\n    if errs[i+len(years1)] < winner[i]:\n        result=\"Win competition\"\n    elif errs[i+len(years1)] < top5[i]:\n        result=\"Top 5 score\"\n    else:\n        for j in range(len(topprctvalues)):\n            if errs[i+len(years1)] < topprctscores[j][i]:\n                result = \"Top \" + str(topprctvalues[j]) + \"%\"\n                break\n        if result is None:\n            result = \"Worst score on Kaggle\"\n\n    print(years2[i], \"{0:.6f}\".format(errs[i+len(years1)]),result+\"\\t\",winner[i],sep=\"\\t\")\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"54c6646b08c127175474b4867121b28091c6db43"},"cell_type":"code","source":"## Create a submission file\nif ROUND2:\n    sub = pd.read_csv(DATA_PATH + 'MSampleSubmissionStage2_2020.csv')\nelse:\n    sub = pd.read_csv(DATA_PATH + 'MSampleSubmissionStage1_2020.csv')\n\n# Create predictor attributes (as above for the CV)\nsub['Season'], sub['Team1'], sub['Team2'] = sub['ID'].str.split('_').str\nsub[['Season', 'Team1', 'Team2']] = sub[['Season', 'Team1', 'Team2']].apply(pd.to_numeric)\n\nsub['deltaSeed'] = sub.apply(delta_seed,axis=1)\nsub['deltaMO'] = sub.apply(delta_ord,axis=1)\nsub['deltaWinPct'] = sub.apply(delta_winPct,axis=1)\ncols = ['PointsFor','PointsAgainst','FGM','FGA','FGM3','FGA3','FTM','FTA','OR','DR','Ast','TO','Stl','Blk','PF']\n\nfor col in cols:\n    print(\"Processing\",col)\n    sub['delta' + col] = sub.apply(delta_stat,args=(col,),axis=1)\n\n# Build the final model\ncols = ['deltaMO', 'deltaWinPct', 'deltaPointsAgainst']\n\n# TODO: Adjust winning probabilities by this percent for selected teams, based on your\nbiases = {\n    '1163':1.2, # U Conn\n    '1181':1.2, # Duke \n    '1437':1.2, # Villanova\n    '1314':1.2, # UNC\n}\n\nXtrain = training_set[cols]\nytrain = training_set['Result']\n\nlogit_model=sm.Logit(ytrain,Xtrain)\nresult=logit_model.fit()\n\n# Make your predictions\nXtest = sub[cols]\npred = result.predict(Xtest)\n\n# Bias results based on team preferences\nfor bias in biases:\n    pred.loc[sub['Team1'] == int(bias)] = pred.loc[sub['Team1'] == int(bias)] * biases[bias] \n    pred.loc[sub['Team2'] == int(bias)] = pred.loc[sub['Team2'] == int(bias)] / biases[bias] \n    \npred.loc[(pred >= 0.9999)] = 0.9999\npred.loc[(pred <= 0.0001)] = 0.0001\n\n\n# Manually adjust some predictions\n# U Conn vs Duke\npred.loc[(sub['Team1'] == 1163) & (sub['Team2'] == 1181)] = 0.8\n\n# Create Submission file\nsub['Pred'] = pred\nsub[['ID', 'Pred']].to_csv('submission.csv', index=False)\n","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":4}