[譯] 使用 Pandas 對 Kaggle 資料集進行統計資料分析

leeyang-tju發表於2018-11-12

有時,當遇到一個資料問題的時候,對於資料集,我們必須首先深入研究並瞭解它。瞭解它的性質,它的分佈等等,這是我們需要專注的領域。

今天,我們將利用 Python Pandas 框架進行資料分析,並利用 Seaborn 進行資料的視覺化。

作為一名極客程式設計師,我的審美觀念很低。Seaborn 對我來說是一種很好的視覺化工具,因為只需要座標點即可。

它在底層使用 Matplotlib 作為繪圖引擎,使用預設的樣式來設定圖形,這使得它們看起來比我所能做的更漂亮。讓我們來看一下資料集,我會給大家展示一種看待不同特徵時的直觀感受。也許我們能從中獲得一些真知灼見呢!

沒有雞蛋就不能做煎蛋卷:資料集。

下面的分析中,我使用的是 120 年的奧運會 資料集,你可以通過點選這個連結來下載或閱讀更多的相關資訊。

我是從 Kaggle 上免費下載該資料集的。如果你需要獲取一個資料集來嘗試一些新的 機器學習演算法,來溫習一些框架的 API,或者只是想要玩一下,Kaggle 是一個很棒的網站。

我將只使用 CSV 檔案中的 ‘athlete_events’,其中記錄了自 1900 年以來的每一場奧運會比賽的運動員資訊,即每個參賽運動員出生地所屬的國家,以及他們是否獲獎等等。

有趣的是, 檔案中的 medals 列中有 85% 的資料是空的,所以平均只有 15% 的奧運會運動員獲得了獎牌。 此外,還有一些運動員獲得了不止一枚獎牌,這表明,在為數不多的奧運級別運動員中,只有更少的人能獲得獎牌。所以他們的功勞是更大的!

開始分析:資料集是什麼樣的?

首先,在深入瞭解該資料集之前,可以先通過一些直觀資料來了解資料集的模式。比如資料集中有多少資料丟失了?資料有多少列?我想先從這些問題開始分析。

我在分析過程中使用 Jupyter 筆記進行,我會為我執行的每段程式碼新增註釋,以便你可以繼續學習。

該 Jupyter 筆記可以在 這個倉庫中 找到,你可以開啟來看一下,並可以從任何一個地方開始。

我首先要做的是使用 Pandas 來載入資料,並檢查它們的大小。

import pandas as pd
import seaborn as sns

df = pd.read_csv('athlete_events.csv')
df.shape
#(271116, 15)
複製程式碼

在這個例子中,資料集中有 15 個不同的列,以及整整 271116 行!也就是超過 27 萬的運動員資料!但是接下來我想知道實際上有多少不同的運動員。還有,他們中有多少人贏得了獎牌?

為了檢視這些資料,首先字資料集上呼叫 ‘list’ 函式列出行資料。我們可以看到許多感興趣的特徵。

list(df)
#['ID','Name','Sex','Age','Height','Weight','Team','NOC','Games','Year','Season','City',
# 'Sport','Event','Medal']
複製程式碼

我能想到的一些事情是,我們可以檢視奧運會運動員的平均身高和體重,或者通過不同的運動來劃分他們。我們還可以檢視依賴於性別的兩個變數的分佈。我們甚至還可以看到每個國家有多少獎牌,將此作為時間序列,來檢視整個二十世紀文明的興衰。

可能性是無限的!但首先讓我們來解決這個難題:我們的資料集有多完整?

def NaN_percent(df, column_name):
    row_count = df[column_name].shape[0]
    empty_values = row_count - df[column_name].count()
    return (100.0*empty_values)/row_count
for i in list(df):
    print(i +': ' + str(NaN_percent(df,i))+'%')  
'''
0% incomplete columns omitted for brevity.
Age: 3.49444518214%
Height: 22.193821095%
Weight: 23.191180159%
Medal: 85.3262072323% --Notice how 15% of athletes did not get any medals
'''
複製程式碼

在序列資料上使用 Pandas 的計數方法可以得到非空行的數量。而通過檢視 shape 屬性,可以檢視到總的行數,不管它們是否為空。

之後就是減法和除法的問題了。我們可以看到只有四欄的屬性不完整:身高、體重、年齡和獎牌。

獎牌屬性的不完整是因為一個運動員可能實際上並沒有贏得獎牌,所以可以預料到這條資料是不完全的。然而,在體重、身高和年齡的方面,不完整的資料讓我們面臨著相當大的挑戰。

我試著用不同的年份對這些資料行進行過濾,但這種不完整性似乎隨著時間的推移而保持一致,這讓我覺得可能是有一些國家不提供運動員的這些相關資料。

開始我們真正的分析: 獎牌情況是怎樣的?

我們問的第一個問題是,自 1900 年以來,有多少不同的人獲得過獎牌?下面的程式碼片段回答了這個問題:

total_rows = df.shape[0]
unique_athletes = len(df.Name.unique())
medal_winners = len(df[df.Medal.fillna('None')!='None'].Name.unique())

"{0} {1} {2}".format(total_rows, unique_athletes, medal_winners)

#'271116 134732 28202'
複製程式碼

正如你所看到的,在過去的 120 年裡,大約有 13.5 萬不同的人蔘加了奧運會,但是隻有 2.8 萬多人獲得了至少一枚獎牌。

獲得獎牌比率大約是五分之一,還不錯。但如果你考慮到許多人實際上會參加多個類別的運動,那就不那麼樂觀了。

既然我們已經分析到這裡了,那麼在這 120 年裡運動員們到底贏得了多少獎牌呢?

# 檢視獎牌分佈
print(df[df.Medal.fillna('None')!='None'].Medal.value_counts())
# 總共多少獎牌
df[df.Medal.fillna('None')!='None'].shape[0]
'''
Gold      13372
Bronze    13295
Silver    13116
Total: 39783
'''
複製程式碼

不出所料,獎牌榜上的分佈幾乎是均勻的:獲得的金牌、銀牌和銅牌的數量幾乎是相同的。

然而,總共頒發了近 3.9 萬枚獎牌,這意味著如果你屬於獲得獎牌最多的那 20% 的運動員,那麼你的平均獎牌數將超過 1 枚。

那麼按照國家來進行分配呢?為了獲得這些資訊,可以執行下面的程式碼片段:

team_medal_count = df.groupby(['Team','Medal']).Medal.agg('count')
# 按照數量進行排列
team_medal_count = team_medal_count.reset_index(name='count').sort_values(['count'], ascending=False)
#team_medal_count.head(40) 用來顯示第一行

def get_country_stats(country):
    return team_medal_count[team_medal_count.Team==country]
# get_country_stats('some_country') 獲得對應國家的獎牌
複製程式碼

使用這個函式我們可以得到某個國家獲得的每種型別的獎牌數量,而通過獲取 Pandas 資料幀頭部以看到獲得獎牌最多的國家。

有趣的是,獎牌數最多國家的第二名仍然是蘇聯,儘管它已經近 20 年沒有出現了。

在所有類別中,第一名是美國,第三名是德國。我還觀察了我的兩個國家——阿根廷和克羅埃西亞,驚訝地發現克羅埃西亞已經贏得了 58 枚金牌,儘管這是從 1991 年(那是 1992 年的奧運會)以來的事情。

寫一段程式碼作為練習,獲取到某一個國家參加奧運會的不同年份資料,我相信你能做到!

女性參與情況

我想到的另一件有趣的事是,從這整個世紀以來,女性在奧運會上的表現如何?這段程式碼回答了這個問題:

unique_women = len(df[df.Sex=='F'].Name.unique())
unique_men = len(df[df.Sex=='M'].Name.unique())
women_medals = df[df.Sex=='F'].Medal.count()
men_medals = df[df.Sex=='M'].Medal.count()

print("{} {} {} {} ".format(unique_women, unique_men, women_medals, men_medals ))

df[df.Sex=='F'].Year.min()

#33808 100979 11253 28530 
#1900
複製程式碼

讓我驚訝的是早在 1900 年就有女性參加了奧運會。然而,從歷史上看,奧運會的男女比例是 3 比 1。驚訝於女性早在 1900 年就參加了奧運會,我決定檢視一下整個時間段裡面她們的參與人數。我終於用到了 Seaborn!

Female participation in the Olympics over time.

我們可以看到,在過去的幾十年裡,女性的參與率一直在快速上升,從幾乎為零上升到數千。然而,她們的參與率真的比男性增長得快嗎?或者這只是世界人口的問題?為了解決這個問題,我做了第二副圖:

f_year_count = df[df.Sex=='F'].groupby('Year').agg('count').Name
m_year_count = df[df.Sex=='M'].groupby('Year').agg('count').Name
(sns.scatterplot(data= m_year_count),
 sns.scatterplot(data =f_year_count))
複製程式碼

Female participation in the Olympics over time.

隨時間推移,女性參與(橙色)對男性參與(藍色)。

這一次,我們可以清楚地看到這樣一個模式的出現:女性的參與數量實際上正在快速地接近男性的數量!另一件有趣的事情是:看到下面的小點了嗎,在右邊?我想那就是冬季奧運會!無論如何,對於女性代表來說,這幅圖看起來相當樂觀,儘管還沒有在哪一年中女性的參與者多於男性。

其它分析:身高和體重

我花了很長時間來檢視身高和體重相關圖,但沒有得到任何有趣的結論。

  • 這兩種屬性在大多數運動中都是呈正態分佈的
  • 在我所觀察過的所有運動中,男性總是比女性更重和更高
  • 唯一有趣的變化似乎是根據此項運動來可以分析兩種性別之間的差別到底有多大。

如果你有任何有趣的想法可以用來分析體重和身高的資料,請告知我!我對每項運動的分組不夠深入,所以可能會有一些錯誤的解釋。以上就是今天的內容,我希望你們覺得這個分析很有趣,或者至少你們學到了一些 Pandas 或者資料分析的相關知識。

我把筆記放在了 GitHub 上,這樣你就可以複製這個專案,可以做你自己的分析,然後提出一個 pull request(拉取請求)。

當然你可以得到所有的功勞!希望你們在圖形顯示和視覺分析上做的比我要好。

第2部分關於運動的深入理解 在這裡可以找到。

可以 在 medium 上關注我 以獲取更多軟體開發和資料科學相關的教程、提示和技巧。 如果你真的喜歡這篇文章,和朋友分享吧!

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章