蓝月亮四肖中特

about云開發

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

打印 上一主題 下一主題

[介紹解說] 實戰案例:足球運動員的數據分析實踐(python)

[復制鏈接]
跳轉到指定樓層
樓主
阿飛 發表于 2020-1-20 15:54:03 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
本帖最后由 阿飛 于 2020-1-20 16:11 編輯

問題導讀

1.本文的背景是什么?
2.數據分析的數據來源是哪里?
3.什么是數據分析?
4.數據分析包含哪些基本流程?


一、本案例的相關說明
本人把這篇文章拿出來進行寫作的主要原因是為了讓大家對數據分析有一個較為清楚的認識,其實數據分析并不是那么高深,只是看你怎么從一堆雜亂無章的數據中能夠發現一定的有規律性的結論,有時候可能會覺得某些結論有些牽強,但這屬于每個人對每個問題而見解不同,因而較強的數據分析能力,需要我們在實際工作中進行慢慢培養出來。同時這篇文章很好的將pandas庫運用到其中,這個也可以幫助我們學以致用,用而學,會起到更好的效果。

1、案例背景
足球運動是最受歡迎的運動之一。在此萬受矚目的運動下,打算針對足球運動員個人的信息,技能水平等各項指標進行相關的分析與統計。例如,我們可能會關注如下的內容:

足球運動員是否受出生日期的影響?
左撇子適合踢足球嗎?
足球運動員的號碼是否與位置相關?
足球運動員的年齡與能力具有怎樣的關聯?

2、任務說明
目前,我們收集到了某年現役運動員的數據集data.csv。我們希望通過該數據集,針對眾多的足球運動員進行分析與統計,從而能夠發現一些關于足球運動員的特征,解開我們上述疑問。

3、數據列名的含義


4、足球場上各位置說明




5、什么是數據分析?
數據分析指的就是利用統計學知識,對一系列雜亂無章的數據進行數據分析前的預處理,同時結合數據的具體應用場景,提煉出數據中的有效信息,幫助我們定位、分析、解決某些問題,高效決策。

6、數據分析的基本流程
明確需求
  • 數據收集
  • 內部數據
  • 購買數據
  • 爬取數據
  • 調查問卷
數據預處理
數據清洗
(1)缺失值
(2)異常值
(3)重復值
數據轉換
數據分析
(1)數據建模
(2)數據可視化
編寫報告


7、理解流程
現在網上最常見的一種比喻數據分析流程的方式,就是利用“炒菜”來對比“數據分析的每個流程”。



1)熟悉數據集
熟悉數據集,就是在進行數據處理之前,應該先熟悉數據,只有對數據充分熟悉之后,才能更好的進行分析。
熟悉數據常用的方法和屬性有shape、head()、tail()、sample()、info()、describe()。

  • shape:以元組形式返回數據集的行、列大小。
  • head()或tail():當數據量過大時,我們不可能直接查看所有數據,這樣會很消耗電腦內存,因此,使用head()或tail(),可以默認返回數據集的前五行、后五行的數據;當向head()或tail()中傳入整數n時,則可以返回任意前n行、后n行的數據。
  • sample():向方法中傳入整數n時,則會從當前數據集中隨機抽樣n條記錄顯示出來,對于我們了解數據很有幫助。
  • info():可以顯示每列的列名、非空值數量、數據類型,內存占用等信息。
  • describe():可以幫助我們掌握數值的分布情況,會返回每個字段的count()、mean()、std()、min()、25%、50%、75%、max()。對于非數值型字段,只會顯示count()計數。



2)缺失值處理
缺失值就是由于某些原因導致部分數據為空。進行缺失值處理之前,首先應該查看是否有缺失值。

① 檢查缺失值的辦法:一般有以下兩種處理方式;

1、通過info查看數據信息。
2、可以通過isnull與sum結合,查看缺失值情況。

[Bash shell] 純文本查看 復制代碼
data.info()
data.isnull().sum(axis=0)


② 缺失值的處理辦法:一般也有兩種處理方式;

1、直接刪除(當某一列或某一行存在大量的缺失值的時候)。
2、采用某個值填充。

③ 直接刪除缺失值
采用dropna()方法,默認刪除所有含有缺失行的數據(即:某一行只有要一個字段缺失,就刪除)。傳入參數how=”all”,只刪除那些全為空的行。


[Bash shell] 純文本查看 復制代碼
# inplace=True表示原地修改數據集
data.dropna(axis=0, inplace=True) 

# 對刪除后缺失值后的數據集,再次進行缺失值統計
data.isnull().sum(axis=1) 


④ 填充
可以采用均值、中位數、眾數、附近值進行填充。
對于缺失值填充,這里做一個簡單的說明:

1、當數據服從正態分布,這時候可以采用均值填充;
2、當數據為偏態分布(不管左偏還是右偏),則采用中位數進行填充;
3、若某個字段為離散型數據,則最好采用眾數填充;
4、若像溫度這樣的數據,前后時刻之間的溫度關聯肯定是最大的,這時采用前后時刻溫度進行填充更好。


3)異常值處理
異常值:就是和正常數據相比,過高或者過低的數據。
異常值檢測:對異常值進行檢測,主要有以下幾種方式:
1、根據業務需求和經驗對不同指標所劃分的范圍,超過指定范圍的數據叫做異常值;
2、繪制箱線圖,大于上邊緣和小于下邊緣的數據叫做異常值;
3、通過descride()函數,可以找出數據的25%和75%分位數,然后把“小于q1+1.5IQR,大于q3+1.5IQR”的數據叫做異常值,q1為25%分位數,q3為75%分位數,IQR= q3- q1的差值。
  異常值處理:主要有三種處理辦法。1、直接刪除;2、把異常值當做缺失值填充;3、把異常值當做特殊情況,研究異常值出現的原因。

4)重復值處理
重復數據,指的是數據集中同樣的記錄有多條。對于這樣的數據一般就是直接刪除。
重復值的檢測:data.duplicated().sum()可以查看,重復數據有多少行。
重復值的刪除:data.drop_duplicates(inplace=True)。
上述函數可以配合使用參數subset=[]和keep進行調整,具體需要的時候,再百度自學。


二、數據分析代碼
1、導入相關的庫

[Bash shell] 純文本查看 復制代碼
import numpy as np 
import pandas as pd 
import matplotlib as  mpl
import matplotlib.pyplot as  plt 
import seaborn as sns
import warnings

# 用來顯示中文標簽
mpl.rcParams["font.family"] = "SimHei"

# 用來顯示負號
mpl.rcParams["axes.unicode_minus"] = False

# 有時候運行代碼時會有很多warning輸出,像提醒新版本之類的,如果不想這些亂糟糟的輸出,可以使用如下代碼
warnings.filterwarnings('ignore')

結果如下:




2、讀取data.csv數據集
① 讀取數據集

[Bash shell] 純文本查看 復制代碼
data = pd.read_csv("G:\\2大數據學習\\data.csv",engine="python",encoding="utf-8-sig")


  • 當文件路徑中存在中文時,需要設置engine參數來指定默認引擎為python,否則會報錯。
  • utf-8-sig這個編碼在windows系統中是常見的。不帶有BOM格式的數據才是標準的utf8,但是在windows下,用記事本打開一個文本文件,另存為utf-8格式后,該文件開頭就會被帶上BOM頭信息。這個時候當我們指定編碼為utf8,會報錯,因此我們就需要指定編碼為utf-8-sig,告訴系統該文件的編碼是帶有BOM格式的utf8編碼文件。



② 熟悉數據集的幾種方式
[Bash shell] 純文本查看 復制代碼
# 查看數據集共有多少行、多少列
data.shape

# 查看數據集的前5行
data.head()

# 查看數據集的后5行
data.tail()

# 隨機從數據集中抽取5行,顯示
data.sample(5)

# 顯示每列的列名、非空值數量、數據類型,內存占用等信息。
data.info()

# 此函數可以幫助我們掌握數據的分布情況
data.describe()


注意:head()、tail()和sample()方法中都可以傳入一個整數值,head(10)表示顯示前10行,tail(10)表示顯示后10行,sample(10)表示任意抽取10行顯示。

③ 設置DataFrame最大顯示列數
DataFrame在顯示數據時,若列數較多,中間會將一些列省略掉,變為省略號,而我們往往又需要查看全部列的情況,這個時候就需要設置DataFrame最大顯示列數。


[Bash shell] 純文本查看 復制代碼
pd.set_option("display.max_columns",500)


④ 選取指定列,進行相關的數據分析
有時候,數據集中的列,并非都是我們分析所需要的,我們可以有選擇性的進行加載,只加載我們需要的信息列(特征列)。


[Bash shell] 純文本查看 復制代碼
columns = ["Name", "Age", "Nationality", "Overall", "Potential", "Club", 
           "Value", "Wage", "Preferred Foot","Position", "Jersey Number", 
           "Joined","Height", "Weight", "Crossing","Finishing","HeadingAccuracy",
           "ShortPassing", "Volleys","Dribbling", "Curve","FKAccuracy","LongPassing",
           "Jumping","Stamina","Strength","Aggression","Interceptions","Positioning",
           "Vision","Penalties","Marking","StandingTackle", "SlidingTackle","GKDiving",
           "GKHandling","GKKicking","GKPositioning", "GKReflexes", "Release Clause"]
           
pd.read_csv("G:\\2大數據學習\\data.csv",engine="python",encoding="utf-8-sig",usecols=columns)

# 查看數據集共有多少行、多少列
data.shape

# 查看數據集的前5行
data.head()

# 查看數據集的后5行
data.tail()

# 隨機從數據集中抽取5行,顯示
data.sample(5)

# 顯示每列的列名、非空值數量、數據類型,內存占用等信息。
data.info()

# 此函數可以幫助我們掌握數據的分布情況
data.describe()


info()方法的結果顯示如下:




截取describe()方法的部分結果如下:




3、缺失值處理
1)查看缺失值

[Bash shell] 純文本查看 復制代碼
data.info()
data.isnull().sum(axis=0)

結果如下:



結果分析:通過上面的展示可以發現,info()方法雖然可以看到哪些字段具有缺失值,但是并不直觀。通過data.isnull().sum(axis=0)結果顯示,可以很清楚的看到哪些字段具有缺失值,有多少個缺失值。

2)刪除缺失值

[Bash shell] 純文本查看 復制代碼
data.dropna(axis=0,inplace=True)
data.isnull().sum(axis=0)


結果如下:




4、異常值處理
① info()方法展示出的信息




結果分析:上圖截取了部分列的結果展示,其中count表示非空記錄數;mean表示該列所有數據的均值;std表示該列所有數據的標準差;min表示該列數據中的最小值;max表示該列數據中的最大值;25%表示該列中有1/4的數據,小于該值;50%表示該列中有1/2的數據,小于該值;75%表示該列中有3/4的數據,小于該值;

② 利用箱線圖,查看異常值
 由于數據集列數太多,因此我隨意選取兩列畫出其箱線圖進行展示。
[Bash shell] 純文本查看 復制代碼
sns.boxplot(data=data[["Age", "Overall"]])


結果如下:




結果分析:此數據集主要是一些打分情況,幾乎沒有什么特別的異常值,同時有時候一些異常值數據的產生也是合理的,并不是能夠隨意刪除的,因此實際生產中,可以按照上述介紹的方法,結合實際業務進行異常值的處理。

5、重復值處理

[Bash shell] 純文本查看 復制代碼
data.duplicated().sum()
# data.drop_duplicates(inplace=True)

結果如下:



結果分析:從上面的結果中可以看出,此數據集中沒有重復的數據,duplicated()函數默認是將兩行完全一樣的記錄,稱之為“重復值”,當然此函數還有一些其他參數,供我們選擇,你可以根據需求,隨意指定某兩行數據有多少個字段相同,可以稱之為“重復值”。當數據集中含有重復值的時候,可以使用這句代碼data.drop_duplicates(inplace=True)原地刪除數據集中的重復值。

6、足球運動員的身高體重分布
1)數據轉換
  想要統計身高與體重的分布情況,由于數據集中的身高與體重數據并不是我們熟悉的身高與體重的單位,同時也并不是數值類型的數據,因此處理之前需要我們先做數據轉換。



  • 1英尺 = 30.48厘米
  • 1英寸 = 2.54厘米
  • 1磅 = 0.45千克



原始數據展示如下:



代碼如下:
[Bash shell] 純文本查看 復制代碼
def tran_height(height):
        v = height.split("'")
        return int(v[0])*30.48 + int(v[1])*2.54

def tran_weight(weight):
        v = int(weight.replace("lbs", "")) 
        return v*0.45




處理后的結果展示如下:





2)繪制核密度圖

[Bash shell] 純文本查看 復制代碼
fig, ax = plt.subplots(1, 2) 
fig.set_size_inches((18, 5))
sns.distplot(data[["Height"]], bins=50, ax=ax[0], color="g") sns.distplot(data["Weight"], bins=50, ax=ax[1])


結果如下:




結果分析:通過上圖展示可以發現,足球運動員的身高和體重的分布近似呈現正態分布,這個也與顯示情況相似,身高和體重處在兩端的人數較少,處在均值附近的人數最多。當數據量足夠大的時候,根據中心極限定理可以知道,數據集的結果幾乎呈現一個正態分布。

7、左撇子適合踢足球嗎?
1)數量上對比

[Bash shell] 純文本查看 復制代碼
number = data["Preferred Foot"].value_counts() 
display(number)

sns.countplot(x="Preferred Foot", data=data)


結果如下:




結果分析:Preferred Foot這個字段指的是足球運動員的慣用腳,通過上圖展示的左腳和右腳的數量上的對比分析可以發現,左腳人數明顯多于右腳的人數。


2)能力上對比

[Bash shell] 純文本查看 復制代碼
data.groupby("Preferred Foot")["Overall"].mean()
sns.barplot(x="Preferred Foot", y="Overall", data=data)

結果如下:




結果分析:Overall這個字段指的是足球運動員的綜合能力評分,這里我們將子球運動員的慣用腳進行分組后,求出足球運動員的綜合能力評分,可以看出左腳和右腳的綜合能力得分,沒有太大區別。


3)位置上對比
  由于在綜合能力上體現不明顯,我們現在通過每個位置,進行更細致的分析。為了分析的客觀性,我們只統計左腳與右腳都超過50人(含50人)的位置。

① 首先,計算哪些位置左右腳球員都達到了50人。


[Bash shell] 純文本查看 復制代碼
t = data.groupby(["Preferred Foot", "Position"]).size() 
t = t.unstack()
t[t < 50] = np.NaN t.dropna(axis=1, inplace=True) 
display(t)

結果如下:








② 然后,我們根據之前計算的那些位置,對數據集進行過濾。
[Bash shell] 純文本查看 復制代碼
display(t.columns)
t2 = data[data["Position"].isin(t.columns)] 
plt.figure(figsize=(18, 10))
sns.barplot(x="Position", y="Overall", hue="Preferred Foot", hue_order=["Left", "Right"], data=t2)



結果如下:




結果分析:從上圖中可以清晰地看出,左腳選手更適合RW(右邊鋒)的位置。而在其他位置上,左右腳的人數差別并沒有顯著性的差異。

8、哪個的俱樂部、國家擁有綜合能力更好的球員(展示top10)。
&#8195;&#8195;由于每個俱樂部、國家隊足球年動員的人數不一,為了統計的客觀性,只考慮人數達到一定規模的俱樂部、國家。

1)俱樂部
[Bash shell] 純文本查看 復制代碼
g = data.groupby("Club")
r = g["Overall"].agg(["mean", "count"]) 
r = r[r["count"] >= 20]
r = r.sort_values("mean", ascending=False).head(10) 
display(r)
r.plot(kind="bar")



結果如下:







2)國家隊

[Bash shell] 純文本查看 復制代碼
g = data.groupby("Nationality")
r = g["Overall"].agg(["mean", "count"])
r = r[r["count"] >= 50]
r = r.sort_values("mean", ascending=False).head(10) 
display(r)
r.plot(kind="bar")

結果如下:




9、哪些俱樂部擁有效力更久的球員(5年及以上)?

[Bash shell] 純文本查看 復制代碼
t = pd.to_datetime(data["Joined"]) 
t = t.astype(np.str)
join_year = t.apply(lambda item: int(item.split("-")[0])) 
over_five_year = (2018 - join_year) >= 5
t2 = data[over_five_year]
t2 = t2["Club"].value_counts()
display(t2) 
t2.iloc[:15].plot(kind="bar")

結果如下:







10、足球運動員是否是出生日期相關?

&#8195;我們現有的數據集中,不含有具體的出生日期,因此,我們使用另外一個數據集,該數據集包含2018年世界杯所有球員。

代碼如下:

[Bash shell] 純文本查看 復制代碼
data2 = pd.read_csv("G:\\2大數據學習\\wc2018-players.csv",engine="python",encoding="utf-8-sig") 
data2.head()
t = data2["Birth Date"].str.split(".", expand=True)
t[0].value_counts().plot(kind="bar")
t[1].value_counts().plot(kind="bar")
t[2].value_counts().plot(kind="bar")

結果如下:



結論如下:對于球員與出生日期這張圖,并看不出一定的規律性,由于樣本量并不夠大,不同日期的球員數量差別10個左右,并不能說明什么問題。對于球員與出生月份這張圖,可以看出年初出生的運動員比年尾出生的運動員多,由于年初出生的運動員和年尾出生的運動員,都是同一年的,但是年初出生的運動員比年尾出生的運動員,要多學習了那么幾個月,因此能力稍微更強、更有一些經驗,因此在同齡人選拔的時候,會更有優勢一些(這個是概率問題,并不是說年尾出生的運動員優秀的不多)。對于球員與出生年份這張圖,可以看出本階段球員中1992年出生的球員最多,1999出生的球員最少。

足球運動員與出生日期是有關的,在年初出生的運動員要明顯多于在年末出生的運動員。


11、足球運動員號碼是否與位置相關?

[Bash shell] 純文本查看 復制代碼
g = data.groupby(["Jersey Number", "Position"]) 
t = g.size()
#display(t)
t = t[t >= 100]
t.plot(kind="bar")


結果如下:




結論如下:球員的號碼與位置是相關的,例如,1號通常都是守門員,9號通常是中鋒等,這個在圖中有著很好的體現。

12、身價與薪水,違約金是否相關?
因為身價與違約金的單位既有M,也有K,為了便于分析,我們統一使用K作為單位,同時,將類型轉換為數值類型,便于統計。


結果如下:



結論如下:從上圖可以看出,足球運動員的身價與薪水和違約金均存在一定的線性關系,但是身價和違約金的線性關系更強(具體是什么樣的線性關系,就需要建模了)。因此可以得出足球運動員的身價與其薪水是緊密關聯的,尤其是違約金,與身價的關聯更大。最下面這張圖是隨意畫的球員身價與升高的關系,可以看出球員身價與升高并沒有什么關系。

13、哪些指標對綜合評分的影響較大?

[Bash shell] 純文本查看 復制代碼
plt.figure(figsize=(25, 25))
sns.heatmap(data.corr(), annot=True, fmt=".2f", cmap=plt.cm.Greens)
plt.savefig("corr.png", dpi=100, bbox_inches="tight")

這張圖就不展示結果了,由于圖太大。


14、年齡與評分具有怎樣的關系?

[Bash shell] 純文本查看 復制代碼
sns.scatterplot(x="Age", y="Overall", data=data)
data["Age"].corr(data["Overall"])
# 對一個數組進行切分,可以將連續值變成離散值。
# bins 指定區間數量(桶數)。bins如果為int類型,則進行等分。此處的區間邊界與為前開后閉。
# pd.cut(t["Age"], bins=4)
# 如果需要進行區間的不等分,則可以將bins參數指定為數組類型。數組來指定區間的邊界。
min_, max_ = data["Age"].min() - 0.5, data["Age"].max()
# pd.cut(t["Age"], bins=[min_, 20, 30, 40, max_])
# pd.cut  默認顯示的內容為區間的范圍,如果我們希望自定義內容(每個區間顯示的內容),可以通過labels參數進行指定。
t = pd.cut(data["Age"], bins=[min_, 20, 30, 40, max_], labels=["弱冠之年", "而立之年","不惑之年","知天命"])
t = pd.concat((t, data["Overall"]), axis=1) 
g = t.groupby("Age") 
display(g["Overall"].mean())
sns.lineplot(y="Overall", marker=" ", ms=30, x="Age", data=t)


結果如下:



結論如下:運動員隨著年齡的增長,球員得到更多的鍛煉與經驗,總體能力提升,綜合能力評分因此也不斷增長,但三十幾歲之后,由于體力等其它因素的影響,綜合能力評分呈現下降趨勢。

加微信w3aboutyun,獲取更多資源



領取100本書+1T資源
http://www.imqdzn.shop/forum.php?mod=viewthread&tid=26480

大數據5個項目視頻
http://www.imqdzn.shop/forum.php?mod=viewthread&tid=25235

名企資源、名企面試題、最新BAT面試題、專題面試題等資源匯總
http://www.imqdzn.shop/forum.php?mod=viewthread&tid=27732



————————————————
作者:Huang supreme
原文鏈接:https://blog.csdn.net/weixin_41261833/article/details/103589518



您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

關閉

推薦上一條 /4 下一條

QQ|小黑屋|about云開發-學問論壇|社區 ( 京ICP備12023829號 )

GMT+8, 2020-2-26 02:09 , Processed in 1.125000 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2018 Comsenz Inc.Designed by u179

快速回復 返回頂部 返回列表
蓝月亮四肖中特 股票推荐·天牛宝专业 新浪财经大盘走势 北京期货配资网 2010年茅台股票行情 红太阳配资 2013长线股票推荐 股票行情实时查询000430大盘实时走势查询 南昌配资 关于基金配资的规定 理财平台排名2017排名