使用Python數據透視表挖掘幸福數據

譯自:Explore Happiness Data Using Python Pivot Tables

作者:Michal Weizman

面對新的數據集的最大挑戰之一就是知道從哪裡開始,以及要關注的重點。 能夠快速總結數百行和列可以節省大量的時間。 您可以使用一個簡單的工具來實現這一點,就是一個數據透視表,可以幫助您以查詢速度對數據進行切片,過濾和分組,並以視覺吸引人的方式表示信息。

數據透視表,它有什麼好的?

您可能已經熟悉了Excel中的數據透視表的概念,它們在1994年被商標名稱數據透視表引入。 該工具使用戶能夠自動對存儲在一個表中的數據進行排序,計數,總計或平均。 在下圖中,我們使用數據透視表功能快速總結了泰坦尼克號數據集。 下表中的較大表格顯示了數據集的第一行?30行,較小的表格是我們創建的數據透視表。

左側的數據透視表根據「Sex 」和「Survived 」列分組數據。 因此,該表顯示了不同生存狀態(0:未生存,1:存活)中每個性別的百分比。 這讓我們能夠快速地看到,婦女的生存機會比男人更好。 右側的表格也使用了Survived列,但這次數據按」Class「分組。

介紹我們的數據集:世界幸福報告

我們使用Excel作為上述例子,但這篇文章將展示內置Pandas函數的內置函數pivot_table的優點。 我們將使用「世界幸福報告」,這是關於全球幸福狀態的調查報告。 該報告按照幸福程度排列了150多個國家,自2012年以來,每年都會發布幾乎每年。我們將使用2015年,2016年和2017年收集的數據,如果您想要遵循,可以下載 。

我們正在運行python 3.6和pandas0.19。

我們可能會回答的一些有趣的問題是:

  • 哪些是世界上最幸福,最不幸福的國家和地區?
  • 幸福是否受到地區的影響?
  • 幸福得分在過去三年中有顯著變化嗎?

我們來匯總我們的數據,快速瀏覽一下:

import pandas as pdimport numpy as np# 讀取數據data = pd.read_csv(data.csv, index_col=0)# 通過Year和Happiness Score排序data.sort_values([Year, "Happiness Score"], ascending=[True, False], inplace=True)#展示前10個數據data.head(10)

每個國家的」Happiness Score「是通過對表中的其他七個變數求和來計算的。 這些變數中的每一個都顯示了從0到10的人口加權平均得分,隨著時間的推移跟蹤,並與其他國家進行了比較。

這些變數是:

  • Economy:人均實際GDP
  • Family:社會支持
  • Health:健康的預期壽命
  • Freedom:讓生活選擇的自由
  • Trust:對腐敗的看法
  • Generosity:慷慨的感覺
  • Dystopia:將每個國家與一個假設國家進行比較,這個國家代表每個關鍵變數的最低國家平均水平,並與殘差有差異,用作回歸基準

每個國家的Happiness Score決定了它的Happiness Rank - 這是其特定年份其他國家的相對位置。 例如,第一行表示,瑞士在2015年被評為最幸福的國家,幸福得分為7.587。 瑞士在冰島前排名第一,得分為7.561。 丹麥在2015年排名第三,依此類推。 有趣的是,西歐在2015年排名前八的排名中排名第七。

我們將專註於最終的Happiness Score,以展示數據透視表的技術方面。

# 預覽數據print("Our data has {0} rows and {1} columns".format(data.shape[0], data.shape[1]))# 檢查缺失值print("Are there missing values? {}".format(data.isnull().any().any()))data.describe()

describe() 方法表明,「Happiness Rank」的範圍從1到158,這意味著一年中受訪國家的最大數量為158個。值得注意的是,「幸福排名」最初是int類型。 事實上,它顯示為浮點,這意味著我們在這個列中有NaN值(我們也可以通過計數行來確定這個值,而這個行數只有470,而不是我們的數據集中的495行)。

「Year 」列沒有任何缺失值。 首先,因為它在數據集中顯示為int,而且 - Year的計數為495,這是我們的數據集中的行數。 通過將Year的計數值與其他列進行比較,似乎我們可以預期每列中有25個預設值(在所有其他列中的年VS470中為495)。

按年份和地區分類數據

關於pandas pivot_table的有趣的事情是您只需一行代碼即可獲得數據的另一個觀點。 大多數的pivot_table參數使用默認值,因此必須添加的唯一必需參數是數據和索引。 雖然這不是強制性的,但我們還將在下一個示例中使用value參數。

  • 數據是不言而喻的 - 您需要使用DataFrame
  • index是要對數據分組的列,分組器,數組(或上一個列表)。 它將顯示在索引列(或列,如果您在列表中傳遞)
  • 值(可選)是您要聚合的列。 如果不指定,那麼該函數將聚合所有數字列。

我們先看看輸出,然後解釋表的生成方式:

pd.pivot_table(data, index= Year, values= "Happiness Score")

通過將Year作為索引參數,我們選擇按Year分組我們的數據。 輸出是一個數據透視表,顯示Year的三個不同值作為索引,Happiness Score作為值。 值得注意的是,匯總默認值是平均值(或平均值),因此「幸福得分」列中顯示的值是所有國家的年平均值。 該表顯示,2016年所有國家的平均水平最高,目前是過去三年來的最低水平。

下面是如何創建這個數據透視表的詳細圖表:

接下來,我們使用Region列作為索引:

pd.pivot_table(data, index = Region, values="Happiness Score")

上面的數據透視表中Happiness Score欄中顯示的數字是與以前一樣的平均值,但這次是每個區域所有年份的平均值(2015年,2016年,2017年)。 這樣展示使得澳大利亞和紐西蘭的平均得分最高,而北美則比較接近。 有趣的是,儘管我們從閱讀數據得到的初步印象,這顯示西歐在絕大多數頂級地區,但西歐計算過去三年的平均水平確實排在第三位。 排名最低的地區是撒哈拉以南非洲地區,而靠近南亞。

創建多索引數據透視表

您可能已經使用groupby() 來實現某些數據透視表功能(以前我們已經演示了如何使用groupby()來分析數據)。 然而,pivot_table() 內置函數提供了簡單的參數名稱和默認值,可以幫助簡化複雜的過程,如多索引。

為了將數據分組多列,我們要做的就是傳遞列名列表。 我們按地區和年份對數據進行分類。

pd.pivot_table(data, index = [Region, Year], values="Happiness Score")

這些示例還顯示了數據透視表的名稱:它允許您旋轉或轉動匯總表,並且此旋轉為我們提供了不同的數據透視圖。 一個可以很好地幫助您快速獲得寶貴見解的方法。

這是查看數據的一種方法,但是我們可以使用columns參數來獲得更好的顯示:

  • 列是您希望將數據分組的上一列的列,grouper,array或列表。 使用它將水平擴展不同的值。

使用Year作為Columns參數將顯示年份的不同值,並將使得更好的顯示,如下所示:

pd.pivot_table(data, index= Region, columns=Year, values="Happiness Score")

使用plot() 可視化數據透視表

如果要查看我們創建的上一個數據透視表的可視化表示,您需要做的就是在pivot_table函數調用結束時添加plot() 您還需要導入相關的繪圖庫)。

%matplotlib inlineimport matplotlib.pyplot as pltimport seaborn as sns# 使用Seaborn sns.set() pd.pivot_table(data, index= Region, columns= Year, values= "Happiness Score").plot(kind= bar)plt.ylabel("Happiness Rank")

可視化表示有助於揭示差異較小。 話雖如此,這也表明,位於美國的兩個地區的幸福級別都在持續下降。

使用aggfunc處理數據

到目前為止,我們已經使用平均值來獲取有關數據的見解,但還有其他重要的值要考慮。 嘗試使用aggfunc參數的時間:

  • aggfunc(可選)接受要在組上使用的函數或函數列表(默認值:numpy.mean)。 如果函數列表被傳遞,則生成的數據透視表將具有頂層是函數名的分層列。

我們添加每個區域的中位數,最小值,最大值和標準偏差。 這可以幫助我們評估平均值的準確程度,如果它真正代表真實的圖像。

pd.pivot_table(data, index= Region, values= "Happiness Score", aggfunc= [np.mean, np.median, min, max, np.std])

看起來像某些地區的極值值可能會影響我們的平均水平超過我們想要的。

  • 例如,中東和北非地區的標準差偏高,所以我們可能想要消除極端的價值。 讓我們看看我們為每個地區計算的價值。 這可能會影響我們看到的表示。
  • 例如,澳大利亞和紐西蘭的標準偏差非常低,並且在三年內都是最幸福的,但是我們也可以假設他們僅僅是兩個國家。

應用自定義函數來刪除異常值

pivot_table允許您將自己的自定義聚合函數作為參數傳遞。 您可以使用lambda函數,也可以創建一個函數。 我們來計算一個特定年份每個地區的平均國家數。 我們可以輕鬆地使用lambda函數,就像這樣:

pd.pivot_table(data, index = Region, values="Happiness Score", aggfunc= [np.mean, min, max, np.std, lambda x: x.count()/3])

標準差最低的最高排名地區只佔兩個國家。 另一方面,撒哈拉以南非洲地區的幸福得分最低,但卻達43個國家。

下一步有趣的做法是從計算中去除極值,看排名是否發生顯著變化。 我們創建一個僅計算介於0.25和0.75之間的值的函數。 我們將使用此函數作為計算每個區域的平均值的方法,並檢查排名是否保持不變。

def remove_outliers(values): mid_quantiles = values.quantile([.25, .75]) return np.mean(mid_quantiles)pd.pivot_table(data, index = Region, values="Happiness Score", aggfunc= [np.mean, remove_outliers, lambda x: x.count()/3])

消除異常值主要影響到擁有更多國家的地區,這是有道理的。

我們可以看到西歐(每年接受調查的21個國家的平均水平)提高了排名。 不幸的是,當我們刪除離群值時,撒哈拉以南非洲地區(平均每年接受調查的39個國家)獲得了更低的排名。

使用字元串操作分類

到目前為止,我們已經根據原始表格中的類別分組了我們的數據。 但是,我們可以搜索類別中的字元串來創建我們自己的組。

例如,看大陸的結果會很有趣。 我們可以通過查找包含亞洲,歐洲等的區域名稱來做到這一點。為此,我們可以先將我們的數據透視表指定給一個變數,然後添加我們的過濾器:

table = pd.pivot_table(data, index = Region, values="Happiness Score", aggfunc= [np.mean, remove_outliers])table[table.index.str.contains(Asia)]

歐洲的結果:

table[table.index.str.contains(Europe)]

差異表明,兩個歐洲地區幸福得分差異較大。 在大多數情況下,去除異常值使得分數更高,但在東亞則不高。

如果要從多個列中提取特定的值,那麼最好使用df.query,因為以前的方法不適用於調整多重索引。 例如,我們可以選擇查看特定年份,以及非洲地區的具體地區。

table = pd.pivot_table(data, index = [Region, Year], values=Happiness Score, aggfunc= [np.mean, remove_outliers])table.query(Year == [2015, 2017] and Region == ["Sub-Saharan Africa", "Middle East and Northern Africa"])

在這個例子中,差異是微不足道的,但有趣的是,自從2012年以來調查報告以來,比較前幾年的信息。

處理丟失的數據

迄今為止,我們已經介紹了pivot_table中最強大的參數,因此如果您在自己的項目中使用此方法進行實驗,那麼您已經可以獲得很多參數。 話雖如此,快速瀏覽剩餘的參數(都是可選的,具有默認值)很有用。 首先要談的是缺少值。

  • dropna類型為boolean,用於表示您不想包含條目全部為NaN的列(默認值:True)
  • fill_value是類型標量,用於選擇替換預設值的值(默認值:無)

我們沒有任何所有條目都是NaN的列,但是值得一提的是,如果我們做了pivot_table,那麼默認情況下會根據dropna定義刪除它們。

我們一直讓pivot_table根據默認設置對待我們的NaN。 fill_value的默認值為None,這意味著我們沒有在數據集中替換缺少的值。 為了證明這一點,我們需要生成一個具有NaN值的數據透視表。 我們可以將每個地區的幸福得分分為三個分位數,並檢查有多少個國家屬於三個分位數(希望至少有一個分位數將缺少值)。

要做到這一點,我們將使用qcut(),它是一個內置的熊貓功能,可以讓您將數據分割成您選擇的任何數位數。 例如,指定 pd.qcut(data["Happiness Score"], 4)將導致四個分位數:

  • 0-25%
  • 25%-50%
  • 50%-75%
  • 75%-100%

# 將Happiness Score分為3個分位數score = pd.qcut(data["Happiness Score"], 4)pd.pivot_table(data, index= [Region, score], values= "Happiness Score", aggfunc= count).head(9)

沒有國家的地區在特定的分位數顯示NaN。 這不是理想的,因為等於NaN的計數不給我們任何有用的信息。 顯示0不太困惑,所以讓我們使用fill_value替換NaN:

# 將幸福分數分為3個分位數score = pd.qcut(data["Happiness Score"], 3)pd.pivot_table(data, index= [Region, score], values= "Happiness Score", aggfunc= count, fill_value= 0)

添加總行/列

最後兩個參數既可選,也可用於改進顯示:

  • margins 是布爾型,允許您添加所有行/列,例如。 小計/總計(默認False)
  • marginins_name是類型字元串,並接受當邊距為True時將包含總計的行/列的名稱(默認為「All」)

讓我們用這些來添加一個我們最後一個表。

# 將幸福分數分為3個分位數score = pd.qcut(data[Happiness Score], 3)# 創建一個數據透視表,只顯示前9個值pd.pivot_table(data, index= [Region, score], values= "Happiness Score", aggfunc= count, fill_value= 0, margins = True, margins_name= Total count)

總結

如果您正在尋找從不同角度檢查數據的方法,那麼pivot_table就是答案。 它很容易使用,它對數字和分類值都有用,它可以通過一行代碼獲得結果。

如果您喜歡挖掘這些數據,並且您有興趣進一步調查,那麼我們建議添加前幾年的調查結果,和/或將其他列與國家信息相結合,如貧困,恐怖,失業等。隨時分享您的 筆記本在下面的評論中,享受你的學習!

推薦閱讀:

打字習慣匹配(Typing Pattern Recognition)有什麼好的演算法實現?
如何看待 CMU New Initiative: CMU AI?
數據挖掘SPSS,Python,《機器學習實戰》先學什麼好?
數據分析中的缺失值問題
有哪些比較好的機器學習、數據挖掘、計算機視覺的訂閱號、微博或者是論壇?

TAG:Python | 数据分析 | 数据挖掘 |