Kaggle賽題-“瘋狂的三月”NACC籃球賽預(yù)測(cè)(1)

比賽介紹及數(shù)據(jù)介紹

賽題地址

首先,很感謝以下幾位作者的鏈接:

【Sports+AI】Kaggle體育比賽預(yù)測(cè)總結(jié)

2019MNACC第四名的解決方案與思路

以上解決方案的kaggle鏈接

raddar大神的 如何只根據(jù)比賽的對(duì)陣信息來(lái)確定球隊(duì)的水平并排名

Paulo Pinto在討論區(qū)分享的Ken Pom數(shù)據(jù)的鏈接

中文的EDA

python可視化

LGB, XGB, LogReg

動(dòng)態(tài)可視化

更多的基礎(chǔ)想法可以參見(jiàn):https://www.kaggle.com/c/google-cloud-ncaa-march-madness-2020-division-1-mens-tournament/notebooks

賽題介紹

賽題為谷歌云和NACC合作對(duì)今年的NCAA男子和女子籃球錦標(biāo)賽的比賽結(jié)果做出預(yù)測(cè)。

比賽分為兩個(gè)階段嫉拐,目前位于階段一:參賽選手利用錦標(biāo)賽過(guò)去的結(jié)果構(gòu)建與測(cè)試模型侥钳。第二階段:等NACC在三月中開(kāi)賽坝冕,進(jìn)行真實(shí)比賽結(jié)果的預(yù)測(cè)膘融。

賽題的本質(zhì):一個(gè)二分類問(wèn)題孩擂,但本賽題采用對(duì)數(shù)損失函數(shù)作為評(píng)價(jià)指標(biāo),目的就是給過(guò)度自信或者不自信的判斷更大的懲罰熟史。

\textrm{LogLoss} = - \frac{1}{n} \sum_{i=1}^n \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)\right]

where

n is the number of games played

\hat{y}_i is the predicted probability of team 1 beating team 2

y_i is 1 if team 1 wins, 0 if team 2 wins

log() is the natural (base e) logarithm

def logloss(true_label, predicted, eps = 1e-15):
    p = np.clip(predicted, eps, 1-eps)   #clip這個(gè)函數(shù)將將數(shù)組中的元素限制在a_min, a_max之間馁害,大于a_max的就使得它等于 a_max,小于a_min,的就使得它等于a_min蹂匹。
    if true_label ==1:
        return - np.log(p)
    return -np.log(1-p)
print(f'Confident Wrong Prediction: \t\t {logloss(1, 0.01):0.4f}')      #logloss(0, 0.99)
print(f'Confident Correct Prediction: \t\t {logloss(0, 0.01):0.4f}')    #logloss(1, 0.99)
print(f'Non-Confident Wrong Prediction: \t {logloss(1, 0.49):0.4f}')    #logloss(0, 0.51)
print(f'Non-Confident Correct Prediction: \t {logloss(0, 0.49):0.4f}')  #logloss(1, 0.51)

結(jié)果如下:

Confident Wrong Prediction:          4.6052
Confident Correct Prediction:        0.0101
Non-Confident Wrong Prediction:      0.7133
Non-Confident Correct Prediction:    0.673

可以看出碘菜,過(guò)度自信or不自信會(huì)產(chǎn)生極大的誤差,而比較中庸的評(píng)價(jià)(0.5左右)的損失相對(duì)來(lái)說(shuō)可以接受。

數(shù)據(jù)介紹

0.分別讀取男子和女子的數(shù)據(jù)

import os
os.getcwd()#獲得當(dāng)前工作目錄
os.chdir('D:\\比賽\\')
import numpy as np
import pandas as pd
pd.set_option('display.max_columns', 100)

import matplotlib as mpl
from matplotlib.patches import Circle, Rectangle, Arc
from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline

import warnings
warnings.filterwarnings("ignore")
import seaborn as sns
plt.style.use('seaborn-dark-palette')

mypal = plt.rcParams['axes.prop_cycle'].by_key()['color'] # Grab the color pal
import gc

men_folder_path = './kaggle/input/google-cloud-ncaa-march-madness-2020-division-1-mens-tournament/'
women_folder_path = './kaggle/input/google-cloud-ncaa-march-madness-2020-division-1-womens-tournament/'
Mstage1_folder_path = 'MDataFiles_Stage1/'
Wstage1_folder_path = 'WDataFiles_Stage1/'

#讀取數(shù)據(jù)M
Mfolder_path = men_folder_path
Mteam_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'Teams.csv')
Mseason_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'Seasons.csv')
Mseed_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'NCAATourneySeeds.csv')
Mregular_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'RegularSeasonCompactResults.csv')
Mnacc_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'NCAATourneyCompactResults.csv')
Mregular_section1['is_regular'] = 1
Mnacc_section1['is_regular'] = 0
Mregular_detail_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'RegularSeasonDetailedResults.csv')
Mnacc_detail_section1 = pd.read_csv(Mfolder_path+Mstage1_folder_path+'M'+'NCAATourneyDetailedResults.csv')
Mregular_detail_section1['is_regular'] = 1
Mnacc_detail_section1['is_regular'] = 0

#讀取數(shù)據(jù)W
Wfolder_path = women_folder_path
Wprefix = 'M'
Wteam_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'Teams.csv')
Wseason_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'Seasons.csv')
Wseed_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'NCAATourneySeeds.csv')
Wregular_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'RegularSeasonCompactResults.csv')
Wnacc_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'NCAATourneyCompactResults.csv')
Wregular_section1['is_regular'] = 1
Wnacc_section1['is_regular'] = 0
Wregular_detail_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'RegularSeasonDetailedResults.csv')
Wnacc_detail_section1 = pd.read_csv(Wfolder_path+Wstage1_folder_path+'W'+'NCAATourneyDetailedResults.csv')
Wregular_detail_section1['is_regular'] = 1
Wnacc_detail_section1['is_regular'] = 0
  1. Team Data
    包含了隊(duì)伍的TeamID炉媒、TeamName、FirstD1Season昆烁、LastD1Season吊骤。
Mteam_section1.sort_values('FirstD1Season', ascending = False).head()
  • MTeams.csv and WTeams.csv
  • 球隊(duì)信息,注意不是每個(gè)球隊(duì)在每個(gè)賽季都有比賽静尼,因?yàn)楸荣悢?shù)據(jù)只包含甲級(jí)部分白粉。
  • 球隊(duì)ID:標(biāo)識(shí)一個(gè)大學(xué)的一只球隊(duì),4位數(shù)字鼠渺,10001999表示男隊(duì)鸭巴,30003999表示女隊(duì),該ID是不會(huì)變的拦盹。
  • 球隊(duì)大學(xué)名稱的簡(jiǎn)潔寫法鹃祖。
  • 球隊(duì)為1級(jí)聯(lián)賽的第一年,最早是1985年普舆,注意這部分只有男隊(duì)恬口。
  • 球隊(duì)為1級(jí)聯(lián)賽的最近的一年,如果目前依然是一級(jí)沼侣,那么該值為2020祖能,同樣也只有男隊(duì)
  • 按照FirstD1Season列排序,我們可以看到D1籃球中的一些最新球隊(duì)蛾洛。 比如 新軍Merrimack养铸!

2.Seasons Data
包含了賽季、賽季起始日期(Dayzero 也就是比賽的0點(diǎn) 后邊可以根據(jù)DayNum判斷比賽進(jìn)程)轧膘、每個(gè)賽季的四大賽區(qū)的名稱钞螟。

Mseason_section1.head()
  • 不同賽季的歷史數(shù)據(jù),包含一些賽季屬性扶供。
  • 賽季表示比賽的年份筛圆,注意當(dāng)前是2020賽季。
  • DayZero表示賽季開(kāi)始的那一天的日期椿浓,結(jié)合DayNum可以計(jì)算當(dāng)前日期太援。
  • RegionW,RegionX,RegionY,RegionZ表示四個(gè)分組區(qū)域,最后四強(qiáng)就是這4個(gè)區(qū)域中各自的最后冠軍扳碍。

3.Tourney Seed Data
包含賽季提岔、NACC錦標(biāo)賽的種子信息、對(duì)應(yīng)的TeamID笋敞。

Mseed_section1.head()

種子:格式為3/4字符組成碱蒙,前3個(gè)如下,例如W01,表示W(wǎng)分區(qū)的1號(hào)種子赛惩,如果有第4位哀墓,可能是a/b,進(jìn)一步區(qū)分前3個(gè)字符相同的球隊(duì)喷兼。 球隊(duì)Id篮绰。

將種子信息和Team Data合并

Wseed_section1.merge(Wteam_section1, validate='many_to_one').head()
  1. Regular Season Results
  • 常規(guī)賽所有比賽信息。
  • 賽季年份季惯。
  • DayNum吠各。
  • 勝利方的Id、分?jǐn)?shù)勉抓,失敗方的Id贾漏、分?jǐn)?shù)。
  • 勝利方是主隊(duì)藕筋、客隊(duì)纵散,還是在第三方球場(chǎng)。如果獲勝團(tuán)隊(duì)是主隊(duì)念逞,則此值為“ H”home困食。如果獲勝團(tuán)隊(duì)是客隊(duì),則該值為“ A”away翎承。如果在中立的球場(chǎng)上進(jìn)行比賽硕盹,則該值為“ N”neutral。
  • 加時(shí)次數(shù)叨咖,大于等于0.

查看主場(chǎng)獲勝的情況和加時(shí)賽的情況

Mregular_section1['WLoc'].value_counts()
H    95878
A    49260
N    16414
Mregular_section1['NumOT'].value_counts()
0    155529
1      4989
2       844
3       152
4        32
5         5
6         1

將數(shù)據(jù)按加時(shí)賽數(shù)目降序進(jìn)行展示

Mregular_section1.sort_values('NumOT', ascending=False).head()

查看WScore和Lscore的分布

'''
#bins ---> 箱數(shù)
#hist瘩例、ked ---> 是否顯示箱/密度曲線
#norm_hist ---> 直方圖是否按照密度來(lái)顯示
#rug ---> 是否顯示數(shù)據(jù)分布情況
#vertical ---> 是否水平顯示
#color ---> 設(shè)置顏色
#label ---> 圖例
#axlabel ---> x軸標(biāo)注
'''
sns.distplot(Mregular_section1['WScore'], label = 'WScore', axlabel = '')
sns.distplot(Mregular_section1['LScore'], label = 'LScore', axlabel = '')
plt.legend()

將常規(guī)賽數(shù)據(jù)和TeamData進(jìn)行合并
suffixes參數(shù) get 避免寫好多rename

#將Mregular_section1與Mteam_section1合并兩次  加入TeamName FirstD1Season LastD1Season 等列 后綴W L 區(qū)分
Mregular_section1 = Mregular_section1.merge(Mteam_section1,left_on=['WTeamID'],right_on=['TeamID'],validate='many_to_one').drop('TeamID',axis=1)
Mregular_section1 = Mregular_section1.merge(Mteam_section1,left_on=['LTeamID'],right_on=['TeamID'],suffixes=('_W', '_L'),validate='many_to_one').drop('TeamID',axis=1)
#將Wregular_section1與Wteam_section1合并兩次  加入TeamName列 后綴W L 區(qū)分
Wregular_section1 = Wregular_section1.merge(Wteam_section1,left_on=['WTeamID'],right_on=['TeamID'],validate='many_to_one').drop('TeamID',axis=1)
Wregular_section1 = Wregular_section1.merge(Wteam_section1,left_on=['LTeamID'],right_on=['TeamID'],suffixes=('_W', '_L'),validate='many_to_one').drop('TeamID',axis=1)
Mregular_section1.head()

分別看男子與女子比賽分差的分布

Mregular_section1['Score_Diff'] = Mregular_section1['WScore'] - Mregular_section1['LScore']
Wregular_section1['Score_Diff'] = Wregular_section1['WScore'] - Wregular_section1['LScore']
sns.distplot(a = Mregular_section1["Score_Diff"], bins=40, color="skyblue", hist=True, kde=False, rug=False, label = 'Men')
sns.distplot(a = Wregular_section1["Score_Diff"], bins=40, color="red", hist=True, kde=False, rug=False, label = 'Women')
plt.legend()

對(duì)常規(guī)賽勝場(chǎng)數(shù)進(jìn)行統(tǒng)計(jì)并可視化

#引入counter  對(duì)每個(gè)隊(duì)的勝場(chǎng)進(jìn)行累計(jì)
Mregular_section1['counter'] = 1
Wregular_section1['counter'] = 1

plt.subplots(figsize=(6, 4))
Most_MWinTeam = pd.DataFrame(Mregular_section1.groupby(['TeamName_W'])['counter'].count().sort_values(ascending = False)[:10])
Most_MWinTeam = Most_MWinTeam.reset_index()
ax = sns.barplot(x='counter', y='TeamName_W', data = Most_MWinTeam, color='blue', orient='h')
ax.set_title('Most Winning (Regular Season) Mens Teams', fontsize=15)

plt.subplots(figsize=(20, 8))
Most_MLoseTeam = pd.DataFrame(Mregular_section1.groupby(['TeamName_L'])['counter'].count().sort_values(ascending = False)[:20])
Most_MLoseTeam = Most_MLoseTeam.reset_index()
ax = sns.barplot(x='counter', y='TeamName_L', data = Most_MLoseTeam, color='blue', orient='h')
ax.set_title('Most Losing (Regular Season) Mens Teams', fontsize=15)
  • 可以看出比賽具有明顯的主場(chǎng)優(yōu)勢(shì)。
  • 曾在2009年出現(xiàn)過(guò)一次六加時(shí)甸各。
  • 無(wú)論是勝分還是負(fù)分垛贤,整體均呈正太分布。
  • 無(wú)論男女趣倾,比賽的分差主要分布在0-20分聘惦,且男子比賽更為集中,可能是實(shí)力差距小造成的儒恋。
  • 在男子比賽中善绎,Duke勝場(chǎng)最多,且很多強(qiáng)隊(duì)例如Kansas诫尽、North carolina等也有著很高的勝場(chǎng)禀酱。而Chicago的負(fù)場(chǎng)最多。
  • 在女子比賽中牧嫉,Connecticut勝場(chǎng)最多剂跟。而Air Force的負(fù)場(chǎng)最多减途。
  1. NCAA Season Results
  • NCAA錦標(biāo)賽顾腊。
  • 賽季年份币他。
  • DayNum。
  • 勝利方的Id臂寝、分?jǐn)?shù)送淆,失敗方的Id墓捻、分?jǐn)?shù)。
  • 勝利方是主隊(duì)坊夫、客隊(duì),還是在第三方球場(chǎng)撤卢。
  • 加時(shí)次數(shù)环凿,大于等于0.

均為中立球場(chǎng)

#如果獲勝團(tuán)隊(duì)是主隊(duì),則此值為“ H”放吩。如果獲勝團(tuán)隊(duì)是客隊(duì)智听,則該值為“ A”。如果在中立的球場(chǎng)上進(jìn)行比賽渡紫,則該值為“ N”到推。
Mnacc_section1['WLoc'].value_counts()
N    2251
Name: WLoc, dtype: int64

加時(shí)賽的次數(shù) 最多僅有一次三加時(shí)的出現(xiàn)

Mnacc_section1['NumOT'].value_counts()
0    2114
1     121
2      15
3       1
Name: NumOT, dtype: int64

該三加時(shí)出現(xiàn)在1995年

Mnacc_section1.sort_values('NumOT', ascending=False).head()

NACC中WScore和LScore的分布

sns.distplot(Mnacc_section1['WScore'], label = 'WScore', axlabel = '')
sns.distplot(Mnacc_section1['LScore'], label = 'LScore', axlabel = '')
plt.legend()

將NACC數(shù)據(jù)和TeamData合并 并得到分差進(jìn)行可視化 并看一下男女比賽中最大分差

#將Mregular_section1與Mteam_section1合并兩次  加入TeamName FirstD1Season LastD1Season 等列 后綴W L 區(qū)分
Mnacc_section1 = Mnacc_section1.merge(Mteam_section1,left_on=['WTeamID'],right_on=['TeamID'],validate='many_to_one').drop('TeamID',axis=1)
Mnacc_section1 = Mnacc_section1.merge(Mteam_section1,left_on=['LTeamID'],right_on=['TeamID'],suffixes=('_W', '_L'),validate='many_to_one').drop('TeamID',axis=1)
#將Wregular_section1與Wteam_section1合并兩次  加入TeamName列 后綴W L 區(qū)分
Wnacc_section1 = Wnacc_section1.merge(Wteam_section1,left_on=['WTeamID'],right_on=['TeamID'],validate='many_to_one').drop('TeamID',axis=1)
Wnacc_section1 = Wnacc_section1.merge(Wteam_section1,left_on=['LTeamID'],right_on=['TeamID'],suffixes=('_W', '_L'),validate='many_to_one').drop('TeamID',axis=1)

Mnacc_section1['Score_Diff'] = Mnacc_section1['WScore'] - Mnacc_section1['LScore']
Wnacc_section1['Score_Diff'] = Wnacc_section1['WScore'] - Wnacc_section1['LScore']

sns.distplot(a = Mnacc_section1["Score_Diff"], color="skyblue", hist=True, kde=False, rug=False, label = 'Men')
sns.distplot(a = Wnacc_section1["Score_Diff"], color="red", hist=True, kde=False, rug=False, label = 'Women')
plt.legend()

Wnacc_section1["Score_Diff"].max()
89

Mnacc_section1["Score_Diff"].max()
58

對(duì)NACC的勝場(chǎng)數(shù)進(jìn)行統(tǒng)計(jì)并可視化

#引入counter  對(duì)每個(gè)隊(duì)的勝場(chǎng)進(jìn)行累計(jì)
Mnacc_section1['counter'] = 1
Wnacc_section1['counter'] = 1

plt.subplots(figsize=(20, 8))
Most_MnaccWinTeam = pd.DataFrame(Mnacc_section1.groupby(['TeamName_W'])['counter'].count().sort_values(ascending = False)[:20])
Most_MnaccWinTeam = Most_MnaccWinTeam.reset_index()
ax = sns.barplot(x='counter', y='TeamName_W', data = Most_MnaccWinTeam, color='blue', orient='h')
ax.set_title('Most Winning (NACC Season) Mens Teams', fontsize=15)

plt.subplots(figsize=(20, 8))
Most_MnaccLoseTeam = pd.DataFrame(Mnacc_section1.groupby(['TeamName_L'])['counter'].count().sort_values(ascending = False)[:20])
Most_MnaccLoseTeam = Most_MnaccLoseTeam.reset_index()
ax = sns.barplot(x='counter', y='TeamName_L', data = Most_MnaccLoseTeam, color='blue', orient='h')
ax.set_title('Most Losing (NACC Season) Mens Teams', fontsize=15)

  • NACC均為中立球場(chǎng),沒(méi)有主場(chǎng)優(yōu)勢(shì)惕澎。
  • NACC曾在1995年出現(xiàn)過(guò)一次三加時(shí)莉测,雙加時(shí)也比較罕見(jiàn)。
  • 無(wú)論是勝分還是負(fù)分唧喉,整體均呈正太分布捣卤。
  • 無(wú)論男女,比賽的分差主要分布在0-20分八孝,且男子比賽更為集中董朝,可能是實(shí)力差距小造成的。女子的最大分差為89分干跛,男子最大的的分差為58分子姜。
  • 與常規(guī)賽相似,在男子比賽中楼入,Duke勝場(chǎng)最多哥捕,且很多強(qiáng)隊(duì)例如Kansas、North carolina等也有著很高的勝場(chǎng)浅辙。而能在負(fù)場(chǎng)上有著不錯(cuò)的排名也證明了球隊(duì)有著不俗的實(shí)力扭弧,因?yàn)槟阈枰M(jìn)入NACC才有資格輸,可以看到Duke记舆、Kansas在負(fù)場(chǎng)榜也名列前茅鸽捻。
  • 在女子比賽中,Connecticut勝場(chǎng)最多。而Stanford御蒲、Duke等的負(fù)場(chǎng)最多衣赶。

6.DetailedResults(Only Men)

  • 基本信息:
  • 自02-03賽季以來(lái)的各種比賽的罰球、防守籃板厚满、失誤等數(shù)據(jù)府瞄。
  • 與第1部分的CompactResult相比,前8列是一致的碘箍,從WTeamId到NumOT遵馆,但是這里會(huì)有其他很多數(shù)據(jù),比如二分球個(gè)數(shù)丰榴、三分球個(gè)數(shù)货邓、發(fā)球個(gè)數(shù)、犯規(guī)次數(shù)等等四濒。
  • 最終分?jǐn)?shù)可以由以下方式表示:2×FGM + FGM3 + FTM换况,即2×進(jìn)球數(shù)+三分球數(shù)+罰球數(shù)=總分。
  • 這里的信息與第1部分中的比賽信息是嚴(yán)格對(duì)應(yīng)的盗蟆。
  • MRegularSeasonDetailedResults.csv
  • 03賽季以來(lái)所有非NCAA錦標(biāo)賽以外的比賽的詳細(xì)信息戈二。
  • MNCAATourneyDetailedResults.csv
  • 03賽季以來(lái)所有NCAA錦標(biāo)賽以外的比賽的詳細(xì)信息。
  • 詳細(xì)指標(biāo)
  • WFGM:投籃命中數(shù)喳资。
  • WFGA:未命中數(shù)觉吭。
  • WFGM3:3分命中數(shù),注意這部分?jǐn)?shù)據(jù)是包含在WFGM中的仆邓。
  • WFGA3:3分未命中數(shù)亏栈。
  • WFTM:罰球命中數(shù)。
  • WFTA:罰球未命中數(shù)宏赘。
  • WOR:進(jìn)攻籃板绒北。
  • WDR:防守籃板。
  • WAst:助攻數(shù)察署。
  • WTO:失誤數(shù)闷游。
  • WStl:搶斷數(shù)。
  • WBlk:蓋帽數(shù)贴汪。
  • WPF:個(gè)人犯規(guī)數(shù)脐往。
  • 失敗方為用L替換W,意思一致扳埂。
Mregular_detail_section1.head(3)

基礎(chǔ)數(shù)據(jù)和細(xì)節(jié)數(shù)據(jù)在特征和數(shù)量上的差異

print(Mregular_section1.shape)
print(Mregular_detail_section1.shape)
print(Mnacc_section1.shape)
print(Mnacc_detail_section1.shape)
(161552, 17)
(87504, 35)
(2251, 17)
(1115, 35)
  • regular_section1 和 nacc_section1 一致 只含有Season业簿、DayNum、WTeamID阳懂、WScore梅尤、LTeamID柜思、LScore、WLoc巷燥、NumOT
  • regular_detail_section1 和 nacc_detail_section1 一致 且均有以上列
  • 唯一的區(qū)別是年份 前者始于1985 后者始于2003

將數(shù)據(jù)進(jìn)行合并進(jìn)行更多的討論

#對(duì)于概況數(shù)據(jù)
#將常規(guī)賽和NCC比賽進(jìn)行合并  并排序
section1 = Mregular_section1.append(Mnacc_section1, ignore_index=True).sort_values(by=['Season','DayNum'])
#將數(shù)據(jù)和seed_section1聯(lián)結(jié)  加入輸贏球隊(duì)的賽區(qū)種子
#section1 = section1.merge(Mseed_section1,left_on=['Season','WTeamID'],right_on=['Season','TeamID']).drop('TeamID',axis=1)
#section1 = section1.merge(Mseed_section1,left_on=['Season','LTeamID'],right_on=['Season','TeamID'],suffixes=('_W', '_L')).drop('TeamID',axis=1)
#將數(shù)據(jù)和season_section1進(jìn)行聯(lián)結(jié)   加入DayZero RegionW RegionX RegionY RegionZ 等列
section1 = section1.merge(Mseason_section1,left_on=['Season'],right_on=['Season'])
#將數(shù)據(jù)和team_section1進(jìn)行聯(lián)結(jié)兩次   加入TeamName FirstD1Season LastD1Season 等列 后綴W L 區(qū)分   前邊已經(jīng)進(jìn)行過(guò)一次操作
#section1 = section1.merge(Mteam_section1,left_on=['WTeamID'],right_on=['TeamID']).drop('TeamID',axis=1)
#section1 = section1.merge(Mteam_section1,left_on=['LTeamID'],right_on=['TeamID'],suffixes=('_W', '_L')).drop('TeamID',axis=1)
section1 = section1.sort_values(by=['Season','DayNum'])
section1.shape

#對(duì)于詳細(xì)數(shù)據(jù)
section1_detail = Mregular_detail_section1.append(Mnacc_detail_section1, ignore_index=True).sort_values(by=['Season','DayNum'])
#section1_detail = section1_detail.merge(Mseed_section1,left_on=['Season','WTeamID'],right_on=['Season','TeamID']).drop('TeamID',axis=1)
#section1_detail = section1_detail.merge(Mseed_section1,left_on=['Season','LTeamID'],right_on=['Season','TeamID'],suffixes=('_W', '_L')).drop('TeamID',axis=1)
section1_detail = section1_detail.merge(Mseason_section1,left_on=['Season'],right_on=['Season'])
section1_detail = section1_detail.merge(Mteam_section1,left_on=['WTeamID'],right_on=['TeamID']).drop('TeamID',axis=1)
section1_detail = section1_detail.merge(Mteam_section1,left_on=['LTeamID'],right_on=['TeamID'],suffixes=('_W', '_L')).drop('TeamID',axis=1)
section1_detail = section1_detail.sort_values(by=['Season','DayNum'])
section1_detail.shape

Count of Champion and second(冠軍赡盘、亞軍的次數(shù)可視化)

##利用DayNum == 154  將每一年的決賽取出
final_round = section1.query('DayNum == 154')
#plt.figure來(lái)設(shè)置窗口尺寸。
plt.subplots(figsize=(20, 8))
#wspace = 0.2 為子圖之間的空間保留的寬度缰揪,平均軸寬的一部分
#hspace = 0.2 為子圖之間的空間保留的高度陨享,平均軸高度的一部分
plt.subplots_adjust(wspace=0, hspace=.6)

plt.subplot(2,1,1)
#rotation代表lable顯示的旋轉(zhuǎn)角度。
plt.xticks(rotation=30)
sns.countplot(x="TeamName_W", data=final_round)

plt.subplot(2,1,2)
plt.xticks(rotation=30)
sns.countplot(x="TeamName_L", data=final_round)

每一年決賽的分?jǐn)?shù)走勢(shì)

final_round['Score_diff'] = final_round['WScore'] - final_round['LScore']
sns.lineplot(data=final_round[['Season','WScore','LScore','Score_diff']].set_index('Season'))
plt.legend(loc = 1)
  • 冠軍數(shù)最多的是杜克大學(xué)钝腺,共獲得5次錦標(biāo)賽冠軍抛姑,其次是北卡和康涅狄格州,分別獲得4次冠軍
  • 亞軍數(shù)最多的是杜克和密歇根大學(xué)艳狐,均為4次途戒,其次是堪薩斯的3次
  • 近年來(lái)決賽的分差較小

對(duì)進(jìn)32強(qiáng)、16強(qiáng)僵驰、8強(qiáng)、4強(qiáng)唁毒、決賽的次數(shù)進(jìn)行統(tǒng)計(jì)并可視化

#根據(jù)DayNum確定比賽階段  根據(jù)TeamName_W進(jìn)行分組 對(duì)Season進(jìn)行累計(jì)
team32 = section1.query('DayNum == 136 or DayNum == 137').groupby('TeamName_W')['Season'].count().rename('Count32').reset_index().sort_values(by='Count32',ascending=False).iloc[:10]
team16 = section1.query('DayNum == 138 or DayNum == 139').groupby('TeamName_W')['Season'].count().rename('Count16').reset_index().sort_values(by='Count16',ascending=False).iloc[:10]
team8 = section1.query('DayNum == 143 or DayNum == 144').groupby('TeamName_W')['Season'].count().rename('Count8').reset_index().sort_values(by='Count8',ascending=False).iloc[:10]
team4 = section1.query('DayNum == 145 or DayNum == 146').groupby('TeamName_W')['Season'].count().rename('Count4').reset_index().sort_values(by='Count4',ascending=False).iloc[:10]
team2 = section1.query('DayNum == 152').groupby('TeamName_W')['Season'].count().rename('Count2').reset_index().sort_values(by='Count2',ascending=False).iloc[:10]

plt.subplots(figsize=(20, 10))

plt.subplot(2,3,1)
plt.xticks(rotation=30)
sns.barplot(x="TeamName_W", y='Count32', data=team32)
plt.subplot(2,3,2)
plt.xticks(rotation=30)
sns.barplot(x="TeamName_W", y='Count16', data=team16)
plt.subplot(2,3,3)
plt.xticks(rotation=30)
sns.barplot(x="TeamName_W", y='Count8', data=team8)
plt.subplot(2,3,4)
plt.xticks(rotation=30)
sns.barplot(x="TeamName_W", y='Count4', data=team4)
plt.subplot(2,3,5)
plt.xticks(rotation=30)
sns.barplot(x="TeamName_W", y='Count2', data=team2)
  • 進(jìn)入32強(qiáng)最多的球隊(duì)是堪薩斯的32次
  • 進(jìn)入16強(qiáng)最多的球隊(duì)是杜克的25次
  • 進(jìn)入8強(qiáng)最多的球隊(duì)是肯塔基的17次蒜茴;
  • 進(jìn)入4強(qiáng)最多的球隊(duì)是杜克的12次;
  • 進(jìn)入決賽最多的球隊(duì)是杜克的9次浆西;
  • 其中結(jié)合之前的分析粉私,杜克大學(xué)9次進(jìn)入決賽,最終獲得5次冠軍近零,4次亞軍的傲人成績(jī)

看一下每一賽季NACC比賽階段的平均分差

#section1.groupby(['is_regular','DayNum'])['Season'].count()
tournament = section1.query('DayNum >= 134 and DayNum <= 154')
tournament['ScoreDiv'] = tournament['WScore'] - tournament['LScore']
tournament = tournament.groupby('Season')[['WScore','LScore','ScoreDiv']].mean().reset_index()

plt.subplots(figsize=(20, 5))
sns.barplot(x="Season", y='ScoreDiv', data=tournament)
  • 錦標(biāo)賽平均分差最大的是1993年
  • 錦標(biāo)賽平均分差最小的是1985年
  • 近5年平均分差在11分左右
  • 各個(gè)賽季之間差異不大

將決賽的數(shù)據(jù)和種子信息和賽區(qū)信息進(jìn)行合并 探究種子號(hào)數(shù)和賽區(qū)和奪冠之間的關(guān)系

  • 種子長(zhǎng)度為4的提取中間兩位 為3的提取后兩位
  • 種子第一位可以獲取屬于哪個(gè)賽區(qū) 和Region合并 再取對(duì)應(yīng)列的數(shù)據(jù) 即為賽區(qū)
section1 = section1.merge(Mseed_section1,left_on=['Season','WTeamID'],right_on=['Season','TeamID']).drop('TeamID',axis=1)
section1 = section1.merge(Mseed_section1,left_on=['Season','LTeamID'],right_on=['Season','TeamID'],suffixes=('_W', '_L')).drop('TeamID',axis=1)
final_round = section1.query('DayNum == 154')

'''
其中第一個(gè)字符是W诺核,X,Y或Z(標(biāo)識(shí)團(tuán)隊(duì)所在的區(qū)域)
后兩個(gè)數(shù)字(01久信、02窖杀, ...,15或16)告訴您該區(qū)域內(nèi)的種子裙士。
對(duì)于參加比賽的球隊(duì)入客,第四個(gè)字符(a或b)可以進(jìn)一步區(qū)分種子,因?yàn)樵趨⒓颖荣惖谋荣愔斜舜嗣鎸?duì)的球隊(duì)將擁有前三個(gè)角色相同的種子腿椎。
'''
#根據(jù)Seed的定義   對(duì)其進(jìn)行切分  取出所在區(qū)域  并得到種子號(hào)
final_round['Seed_W_num'] = final_round.Seed_W.apply(lambda seed:int(seed[1:]) if len(seed)==3 else int(seed[1:-1]))
final_round['Seed_L_num'] = final_round.Seed_L.apply(lambda seed:int(seed[1:]) if len(seed)==3 else int(seed[1:-1]))
final_round['Seed_W_code'] = final_round.Seed_W.apply(lambda seed:'Region'+seed[0])
final_round['Seed_L_code'] = final_round.Seed_L.apply(lambda seed:'Region'+seed[0])
#根據(jù)Seed_L_code確定賽區(qū)
final_round['Seed_W_region'] = final_round.apply(lambda row:row[row['Seed_W_code']], axis=1)
final_round['Seed_L_region'] = final_round.apply(lambda row:row[row['Seed_L_code']], axis=1)


plt.subplots(figsize=(20, 10))
plt.subplots_adjust(wspace=0.2, hspace=0.4)
plt.subplot(3,1,1)
sns.countplot(x="Seed_W_num", data=final_round)
plt.subplot(3,1,2)
sns.countplot(x="Seed_W_region", data=final_round)
plt.subplot(3,1,3)
sns.lineplot(x="Season", y="Seed_W_num", estimator=None, data=final_round)
  • 各個(gè)分區(qū)的1號(hào)種子依然是冠軍的大熱門桌硫,共22次獲得冠軍,且冠軍數(shù)量與種子號(hào)基本線性負(fù)相關(guān)啃炸,這說(shuō)明賽前的種子指定的還是相當(dāng)準(zhǔn)確的
  • 賽區(qū)上看铆隘,Midwest獲得冠軍最多,其次是South南用,這說(shuō)明在賽區(qū)這一個(gè)維度上膀钠,實(shí)例是不太平衡的掏湾,這點(diǎn)跟NBA不太一樣,NBA由于存在這工資帽這種機(jī)制托修,使得其各隊(duì)實(shí)力相對(duì)會(huì)被限制到一個(gè)范圍內(nèi)忘巧,而大學(xué)則是有籃球名校的存在的
  • 從獲得冠軍的球隊(duì)種子號(hào)的趨勢(shì)圖看,冠軍越來(lái)越難以出現(xiàn)完全的黑馬睦刃,基本上以1,2,3號(hào)種子中出現(xiàn)砚嘴,當(dāng)然了,并不是說(shuō)3號(hào)種子就不是黑馬

本節(jié)完

下節(jié)帶來(lái) - 比賽詳細(xì)統(tǒng)計(jì)數(shù)據(jù)可視化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涩拙,一起剝皮案震驚了整個(gè)濱河市际长,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兴泥,老刑警劉巖工育,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異搓彻,居然都是意外死亡如绸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門旭贬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)怔接,“玉大人,你說(shuō)我怎么就攤上這事稀轨《笃辏” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵奋刽,是天一觀的道長(zhǎng)瓦侮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)佣谐,這世上最難降的妖魔是什么肚吏? 我笑而不...
    開(kāi)封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮狭魂,結(jié)果婚禮上须喂,老公的妹妹穿的比我還像新娘。我一直安慰自己趁蕊,他們只是感情好坞生,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掷伙,像睡著了一般是己。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上任柜,一...
    開(kāi)封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天卒废,我揣著相機(jī)與錄音沛厨,去河邊找鬼。 笑死摔认,一個(gè)胖子當(dāng)著我的面吹牛逆皮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播参袱,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼电谣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抹蚀?” 一聲冷哼從身側(cè)響起剿牺,我...
    開(kāi)封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎环壤,沒(méi)想到半個(gè)月后晒来,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡郑现,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年湃崩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片接箫。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡攒读,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出列牺,到底是詐尸還是另有隱情,我是刑警寧澤拗窃,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布瞎领,位于F島的核電站,受9級(jí)特大地震影響随夸,放射性物質(zhì)發(fā)生泄漏九默。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一宾毒、第九天 我趴在偏房一處隱蔽的房頂上張望驼修。 院中可真熱鬧,春花似錦诈铛、人聲如沸乙各。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)耳峦。三九已至,卻和暖如春焕毫,著一層夾襖步出監(jiān)牢的瞬間蹲坷,已是汗流浹背驶乾。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留循签,地道東北人级乐。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像县匠,于是被迫代替她去往敵國(guó)和親风科。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361