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()
data.info()
data.isnull().sum(axis=0)
結果分析:通過上面的展示可以發現,info()方法雖然可以看到哪些欄位具有缺失值,但是並不直觀。通過data.isnull().sum(axis=0)結果顯示,可以很清楚的看到哪些欄位具有缺失值,有多少個缺失值。
2)刪除缺失值data.dropna(axis=0,inplace=True)
data.isnull().sum(axis=0)
① info()方法展示出的信息
結果分析:上圖截取了部分列的結果展示,其中count表示非空記錄數;mean表示該列所有數據的均值;std表示該列所有數據的標準差;min表示該列數據中的最小值;max表示該列數據中的最大值;25%表示該列中有1/4的數據,小於該值;50%表示該列中有1/2的數據,小於該值;75%表示該列中有3/4的數據,小於該值。
② 利用箱線圖,查看異常值
由於數據集列數太多,因此我隨意選取兩列畫出其箱線圖進行展示。
sns.boxplot(data=data[["Age", "Overall"]])
結果分析:此數據集主要是一些打分情況,幾乎沒有什麼特別的異常值,同時有時候一些異常值數據的產生也是合理的,並不是能夠隨意刪除的,因此實際生產中,可以按照上述介紹的方法,結合實際業務進行異常值的處理。
5、重複值處理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千克
原始數據展示如下:
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
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、左撇子適合踢足球嗎?number = data["Preferred Foot"].value_counts()
display(number)
sns.countplot(x="Preferred Foot", data=data)
結果分析:Preferred Foot這個欄位指的是足球運動員的慣用腳,通過上圖展示的左腳和右腳的數量上的對比分析可以發現,左腳人數明顯多於右腳的人數。
2)能力上對比data.groupby("Preferred Foot")["Overall"].mean()
sns.barplot(x="Preferred Foot", y="Overall", data=data)
結果分析:Overall這個欄位指的是足球運動員的綜合能力評分,這裡我們將子球運動員的慣用腳進行分組後,求出足球運動員的綜合能力評分,可以看出左腳和右腳的綜合能力得分,沒有太大區別。
3)位置上對比由於在綜合能力上體現不明顯,我們現在通過每個位置,進行更細緻的分析。為了分析的客觀性,我們只統計左腳與右腳都超過50人(含50人)的位置。
① 首先,計算哪些位置左右腳球員都達到了50人。
t = data.groupby(["Preferred Foot", "Position"]).size()
t = t.unstack()
t[t < 50] = np.NaN t.dropna(axis=1, inplace=True)
display(t)
② 然後,我們根據之前計算的那些位置,對數據集進行過濾。
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)。由於每個俱樂部、國家隊足球年動員的人數不一,為了統計的客觀性,只考慮人數達到一定規模的俱樂部、國家。
1)俱樂部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")
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")
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")
我們現有的數據集中,不含有具體的出生日期,因此,我們使用另外一個數據集,該數據集包含2018年世界盃所有球員。
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、足球運動員號碼是否與位置相關?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作為單位,同時,將類型轉換為數值類型,便於統計。
def to_numeric(item):
item = item.replace("€", "")
value = float(item[:-1])
if item[-1] == "M":
value *= 1000
return value
data["Value"] = data["Value"].apply(to_numeric)
data["Wage"] = data["Wage"].apply(to_numeric)
data["Release Clause"] = data["Release Clause"].apply(to_numeric) data.head()
sns.scatterplot(x="Value", y="Wage", data=data)
sns.scatterplot(x="Value", y="Release Clause", data=data)
sns.scatterplot(x="Value", y="Height", data=data)
結論如下:從上圖可以看出,足球運動員的身價與薪水和違約金均存在一定的線性關係,但是身價和違約金的線性關係更強(具體是什麼樣的線性關係,就需要建模了)。因此可以得出足球運動員的身價與其薪水是緊密關聯的,尤其是違約金,與身價的關聯更大。最下面這張圖是隨意畫的球員身價與升高的關係,可以看出球員身價與升高並沒有什麼關係。
13、哪些指標對綜合評分的影響較大?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、年齡與評分具有怎樣的關係?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)
結論如下:運動員隨著年齡的增長,球員得到更多的鍛鍊與經驗,總體能力提升,綜合能力評分因此也不斷增長,但三十幾歲之後,由於體力等其它因素的影響,綜合能力評分呈現下降趨勢。
長按二維碼關注我們
數據森麟公眾號的交流群已經建立,許多小夥伴已經加入其中,感謝大家的支持。大家可以在群裡交流關於數據分析&數據挖掘的相關內容,還沒有加入的小夥伴可以掃描下方管理員二維碼,進群前一定要關注公眾號奧,關注後讓管理員幫忙拉進群,期待大家的加入。
管理員二維碼: