【數據科學系統學習】Python # 數據分析基本操做[四] 數據規整化和數據聚合與分組運算

本篇內容爲整理《利用Python進行數據分析》,博主使用代碼爲 Python3,部份內容和書本有出入。python

在前幾篇中咱們介紹了 NumPy、pandas、matplotlib 三個庫的基本操做,本篇介紹對數據的一些操做。正則表達式

  • 數據規整化:清理、轉換、合併、重塑
  • 數據聚合與分組運算

數據規整化:清理、轉換、合併、重塑

合併數據集

  • pandas.merge:可根據一個或多個鍵將不一樣DataFrame中的行連接起來。
  • pandas.concat:可沿着一條軸將多個對象堆疊到一塊兒。
  • combine_first:可將重複數據編接在一塊兒,用一個對象中的值填充另外一個對象中的缺失值。

數據庫風格的 DataFrame 合併數據庫


數據集的合併或鏈接運算:經過一個或多個鍵將行連接起來。數組

clipboard.png

多對一的合併:app

clipboard.png

若沒有指定用哪一個列進行鏈接,merge會將重疊列名當作鍵,指定以下:dom

clipboard.png

若兩個對象的列名不一樣,可分別進行指定:函數

clipboard.png

默認狀況下,mergeinner鏈接,結果中的鍵是交集。外鏈接求取的是鍵的並集:工具

clipboard.png

多對多的合併操做:大數據

clipboard.png

鏈接方式隻影響出如今結果中的鍵。優化

根據多個鍵進行合併,傳入一個由列名組成的列表:

clipboard.png

在進行列-列鏈接時,DataFrame對象中的索引會被丟棄。

suffixes選項:指定附加到左右兩個DataFrame對象的重疊列名上的字符串。

clipboard.png


索引上的合併


DataFrame中的鏈接鍵位於其索引中時,傳入left_index=Trueright_index=True,以說明索引應該被用做鏈接鍵:

clipboard.png

clipboard.png


對於層次化索引的數據:

clipboard.png

必須以列表的形式指明用做合併鍵的列(注意對重複索引值的處理):

clipboard.png

使用合併雙方的索引:

clipboard.png


DataFramejoin 實例方法:

clipboard.png

clipboard.png

更方便的實現按索引合併,無論有沒有重疊的列。在鏈接鍵上做左鏈接。


支持參數DataFrame的索引跟調用者DataFrame的某個列之間的鏈接:

clipboard.png

clipboard.png

對於簡單的索引合併,能夠向join傳入一組DataFrame(concat 函數也是這個功能):

clipboard.png


軸向鏈接


數據合併運算:

  • 鏈接(concatenation)
  • 綁定(binding)
  • 堆疊(stacking)

NumPy有一個用於合併原始NumPy數組的concatenation函數:

clipboard.png

pandasconcat函數:

clipboard.png

默認狀況下,concataxis=0 上工做,產生一個新Series。傳入 axis=1,產生一個DataFrame

clipboard.png

這種狀況下,另一條軸上沒有重疊,傳入 join = 'inner' 獲得它們的交集:

clipboard.png

使用 key 參數,在鏈接軸上建立一個層次化索引:

clipboard.png

沿着 axis=1Series進行合併,keys 就會成爲DataFrame的列頭:

clipboard.png

DataFrame對象也是如此:

clipboard.png

傳入一個字典,則字典的鍵會被當作keys選項的值:

clipboard.png

用於管理層次化索引建立方式的參數:

clipboard.png

跟當前分析工做無關的DataFrame行索引:

clipboard.png

傳入 ignore_index = True

clipboard.png


合併重疊數據


關於有索引所有或部分重疊的兩個數據集。

NumPywhere函數,用於表達一種矢量化的if-else

clipboard.png

clipboard.png

Seriescombine_first方法,實現與上面同樣的功能,並會進行數據對齊:

clipboard.png

對於DataFrame 同樣:

clipboard.png

clipboard.png

能夠看做用參數對象中的數據爲調用者對象的缺失數據「打補丁」。


重塑和軸向旋轉

用於從新排列表格型數據的基礎運算:重塑(reshape)或軸向旋轉(pivot)。


重塑層次化索引


  • stark:將數據的列「旋轉」爲行
  • unstark:將數據的行「旋轉」爲列

clipboard.png

stack方法將行轉爲列,獲得一個Series

clipboard.png

對層次化索引的Series,能夠用unstack將其從新排爲一個DataFrame

clipboard.png

默認狀況下,unstack操做最內層。

傳入分層級別的編號或名稱可對其餘級別進行unstack操做:

clipboard.png

若是不是全部的級別值都能在各分組找到的話,unstack操做可能會引入缺失數據:

clipboard.png

stack默認會濾除缺失數據,所以該運算是可逆的:

clipboard.png

DataFrame進行unstack操做時,做爲旋轉軸的級別將會成爲結果中的最低級別:

clipboard.png

clipboard.png


將「長格式」旋轉爲「寬格式」


時間序列數據一般以 「長格式(long)」或「堆疊格式(stacked)」存儲在數據庫和 CSV 中。

clipboard.png

轉成DataFrame,用 pivot 方法:

clipboard.png

clipboard.png

獲得的DataFrame帶有層次化的列:

clipboard.png

假設有兩個須要參與重塑的數據列:

clipboard.png

pivot其實只是一個快捷方式:用set_index建立層次化索引,再用unstack重塑。

clipboard.png


以上是數據的重排,下面是過濾、清理及其餘轉換工做。

數據轉換

移除重複數據


DataFrame中出現的重複行:

clipboard.png

DataFrameduplicated方法返回一個布爾型Series,表示各行是不是重複行,drop_duplicates方法返回一個移除了重複行的DataFrame

clipboard.png

指定部分列進行重複項判斷,如只但願根據k1列過濾重複項:

clipboard.png

duplicateddrop_duplicates默認保留重複數值裏第一次出現的組合,傳入keep = last則保留最後一個:

clipboard.png


利用函數或映射進行數據轉換


根據數組、SeriesDataFrame列中的值來實現轉換。

clipboard.png

編寫一個肉類到動物的映射:

clipboard.png

Seriesmap方法:能夠接受一個函數或含有映射關係的字典型對象,用於修改對象的數據子集。

clipboard.png

也能夠傳入一個可以完成所有這些工做的函數:

clipboard.png


替換值


replace方法 :替換

利用fillna方法填充缺失數據能夠看做替換的一種特殊狀況。

替換一個值和一次性替換多個值:

clipboard.png

對不一樣的值進行不一樣的替換:

clipboard.png

傳入的參數也能夠是字典:

clipboard.png


重命名軸索引


軸標籤有一個map方法:

clipboard.png

對函數或映射進行轉換,從而獲得一個新對象。


將其值賦給index,就能夠對DataFrame進行就地修改了:

clipboard.png


要建立數據集的轉換版,而不是修改原始數據,用rename

clipboard.png

rename結合字典型對象能夠實現對部分軸標籤的更新:

clipboard.png

rename實現了複製DataFrame並對其索引和列標籤進行賦值,就地修改某個數據集,傳入inplace=True

clipboard.png


離散化和麪元劃分


爲了便於分析,連續數據經常被離散化或拆分爲「面元(bin)」。

pandascut函數:

clipboard.png

pandas返回的是一個特殊的Categorical對象,它含有一個表示不一樣分類名稱的數組和一個爲年齡數據進行標號的屬性:

clipboard.png

哪邊是閉端能夠經過right=False進行修改:

clipboard.png

設置本身的面元名稱:

clipboard.png

labels選項設置爲一個列表或數組便可。


若是向cut傳入的是面元的數量而不是確切的面元邊界,則它會根據數據的最小值和最大值計算等長面元:

clipboard.png

將一些均勻分佈的數據分紅了四組。


qcut函數:根據樣本分位數對數據進行面元劃分。

因爲qcut使用的是樣本分位數,能夠獲得大小基本相等的面元(而 cut 根據數據的分佈狀況,可能沒法使各個面元中含有相同數量的數據點)。

clipboard.png

clipboard.png

設置自定義的分位數:

clipboard.png

在聚合和分組運算時會再次用到cutqcut 這兩個離散化函數。


檢測和過濾異常值


判斷是否存在異常值(outlier ):

clipboard.png

找出某列中絕對值大小超過 3 的值:

clipboard.png

選出所有含有「超過 3 或 -3 的值」的行:

clipboard.png

將值限制在區間 -3 到 3 之內:

clipboard.png

np.sign這個ufunc返回的是一個由 1 和 -1 組成的數組,表示原始值的符號。


排列和隨機採樣


numpy.random.permutation函數:對SeriesDataFrame的列排列。

clipboard.png

Permutation(5):須要排列的軸的長度。

而後就能夠在基於ix的索引操做或take函數中使用該數組了:

clipboard.png

選取隨機子集(非替換):

clipboard.png

用替換的方式產生樣本:

clipboard.png


計算指標/啞變量


將分類變量(Categorical)轉換爲「啞變量矩陣(dummy matrix)」或「指標矩陣(indicator matrix)」。

clipboard.png

DataFrame的列加上一個前綴,以便可以跟其餘數據進行合併:

clipboard.png

get_dummiesprefix參數。


DataFrame中的某行同屬於多個分類的狀況,舉個例子:

clipboard.png

要爲每一個genre添加指標變量就須要作一些數據規整操做,構建多成員指標變量:

clipboard.png

對於很大的數據,這種方式會變得很是慢,須要編寫一個可以利用DataFrame內部機制的更低級的函數:

clipboard.png

get_dummiescut之類的離散化函數。


字符串操做

字符串對象方法


Python 字符串對象的內置方法:

clipboard.png

find找不到返回 -1,index找不到引起一個異常

clipboard.png


傳入空字符串經常用於刪除模式:

clipboard.png


正則表達式(regex)


提供了一種靈活的在文本中搜索或匹配字符串模式的方式。python 內置的re模塊負責對字符串應用正則表達式。

re模塊的函數分爲三個大類:模式匹配、替換、拆分。

clipboard.png

描述一個或多個空白符的regex\s+

調用re.split('\s+', text)時,正則表達式會先被編譯,而後再在text上調用其split方法。

能夠用re.compile本身編譯一個regex,以獲得一個可重用的regex對象,如上所示。若是打算對許多字符串應用同一條正則表達式,強烈建議經過這種方法,能夠節省大量的 CPU 時間。


獲得匹配regex的全部模式:

clipboard.png

  • findall:返回字符串中全部的匹配項。
  • search:只返回第一個匹配項。
  • match:只匹配字符串的首部。

clipboard.png


sub方法:將匹配到的模式替換爲指定字符串,並返回所獲得的新字符串。

clipboard.png

不只想找出電子郵件地址,還想將各個地址分爲 3 個部分,只需將待分段的模式的各部分用圓括號包起來:

clipboard.png

經過groups方法返回一個由模式各段組成的元組。


對於帶有分組功能的模式,findall會返回一個元組列表:

clipboard.png

sub還能經過諸如\1, \2之類的特殊符號訪問各匹配項中的分組:

clipboard.png

爲各個匹配分組加上一個名稱,由這種正則表達式所產生的匹配對象能夠獲得一個簡單易用的帶有分組名稱的字典:

clipboard.png


pandas 中矢量化的字符串函數


經過data.map,全部字符串和正則表達式方法都能被應用於各個值,但如存在NA就會報錯,爲了解決這個問題,Series有一些可以跳過NA值的字符串操做方法,經過Seriesstr屬性便可訪問這些方法:

clipboard.png

也能夠用正則表達式:

clipboard.png

實現矢量化的元素獲取操做,對str.get/str屬性上使用索引:

clipboard.png

對字符串進行子串截取:

clipboard.png


數據聚合與分組運算

對數據集進行分組並對各組應用一個函數。

在將數據集準備好以後,一般的任務就是計算分組統計生成透視表pandas提供了一個靈活高效的gruopby功能,對數據集進行切片、切塊、摘要等操做。

pythonpandas強大的表達能力能夠執行復雜的多的分組運算:利用任何能夠接受pandas對象或NumPy數組的函數。


GroupBy技術

分組運算:split(拆分)--apply(應用)--combine(合併)。

分組鍵的形式:

  • 列表或數組,其長度與待分組的軸同樣。
  • 表示DataFrame某個列名的值。
  • 字典或Series,給出待分組軸上的值與分組名之間的對應關係。
  • 函數,用於處理軸索引或索引中的各個標籤。

clipboard.png

訪問data1,並根據key1調用groupby

變量grouped是一個GroupBy對象,它實際上尚未進行任何計算,只是含有一些有關分組鍵df['key1']的中間數據。

例如,調用GroupBymean方法來計算分組平均值:

clipboard.png

Series根據分組鍵進行了聚合,產生了一個新的Series,其索引爲key1列中的惟一值。

經過兩個鍵對數據進行了分組後,獲得的Series具備一個層次化索引:

clipboard.png

分組鍵能夠是任何長度適當的數組:

clipboard.png

將列名用做分組鍵:

clipboard.png

GroupBysize方法返回一個含有分組大小的Series

clipboard.png


對分組進行迭代


GroupBy對象支持迭代,能夠產生一組二元元組(由分組名和數據塊組成)。

clipboard.png

對於多重鍵,元組的第一個元素將會是由鍵值組成的元組。

對數據片斷進行操做,如將這些數據片斷作成一個字典:

clipboard.png

groupby默認在axis=0上進行分組,經過設置能夠在其它任何軸上進行分組,如能夠根據dtype對列進行分組:

clipboard.png


選取一個或一組列


對於由DataFrame產生的GroupBy對象,用一個或一組(單個字符串或字符串數組)列名對其進行索引,就能實現選取部分列進行聚合的目的:

clipboard.png

例如,對部分列進行聚合:計算data2列的平均值並以DataFrame形式獲得結果:

clipboard.png

返回一個已分組的DataFrame(傳入的是列表或數組)或Series(傳入的是標量形式的單個列名):

clipboard.png


經過字典或 Series 進行分組


除數組之外,分組信息還能夠其餘形式存在

clipboard.png

根據分組計算列的sum

clipboard.png

mapping這個字典傳給groupby便可。

Series做爲分組鍵:

clipboard.png

這裏Series能夠被看作一個固定大小的映射。pandas會檢查Series以確保其索引根分組軸是對齊的。


經過函數進行分組


任何被當作分組鍵的函數都會在各個索引值上被調用一次,其返回值就會被用做分組名稱。

clipboard.png

將函數根數組、列表、字典、Series混合使用(任何東西最終都會被轉換爲數組):

clipboard.png

Key_list和人名對應,再在相同長度的對應一列裏選min的值。


根據索引級別分組


層次化索引數據集經過level關鍵字傳入級別編號或名稱:

clipboard.png


數據聚合

可使用通過優化的GroupBy的方法,還可使用本身發明的聚合運算,還能夠調用分組對象上已經定義好的任何方法,如 quantile能夠計算SeriesDataFrame列的樣本分位數:

clipboard.png

GroupBy會高效地對Series進行切片,而後對各片調用piece.quantile(0.9),最後將這些結果組裝成最終結果。

使用本身的聚合函數,傳入aggregateagg方法便可:

clipboard.png

有些方法如describe也能夠用,但嚴格來說它們並不是聚合運算。

clipboard.png


自定義聚合函數比表中的通過優化的函數慢得多,這是由於在構造中間分組數據塊時存在很是大的開銷(函數調用、數據重排等)。


面向列的多函數應用


根據 'smoker''size'tips 進行分組:

clipboard.png

傳入一組函數或函數名,獲得的DataFrame的列就會以相應的函數命名:

clipboard.png

傳入一個由(name, function )元組組成的列表,各元組的第一個元素會被用做DataFrame的列名:

clipboard.png

對於DataFrame,定義一組應用於所有列的函數,或不一樣的列應用不一樣的函數。

clipboard.png

結果的DataFrame擁有層次化的列。至關於分別對列['tip_pct']和列['total_bill']進行聚合,而後用concat將結果組裝到一塊兒(列名用做 keys 參數)。

傳入帶有自定義名稱的元組列表:

clipboard.png

對不一樣的列應用不一樣的函數:向agg傳入一個從列名映射到函數的字典

clipboard.png

只有將多個函數應用到至少一列時,DataFrame纔會擁有層次化的列:

clipboard.png


以「無索引」的形式返回聚合數據


groupby傳入as_index=False,禁用功能由惟一的分組鍵組成索引:

clipboard.png

clipboard.png


分組級運算和轉換

聚合只是分組運算的其中一種,它接受可以將一維數據簡化爲標量值的函數。

接下來介紹 transformapply 方法,執行更多其餘的分組運算。

爲一個DataFrame添加一個用於存放各索引分組平均值的列:先聚合再合併。

clipboard.png

clipboard.png

下面在GroupBy上使用transform方法:

clipboard.png

clipboard.png

transform會將一個函數應用到各個分組,而後將結果放置到適當的位置上。

從各組中減去平均值:先建立一個距平化函數(demeaning function),而後將其傳給transform

clipboard.png

檢查demeaned如今的分組平均值是否爲 0:

clipboard.png

aggregate同樣,transform也是一個有着嚴格條件的特殊函數,傳入的函數只能產生兩種結果,一個能夠廣播的標量值(如 np.mean) 或一個相同大小的結果數組。


apply:通常性的「拆分-應用-合併」


最通常化的GroupBy方法是applyapply會將待處理的對象拆分紅多個片斷,而後對各片斷調用傳入的函數,最後嘗試將各片斷組合到一塊兒。

根據分組選出最高的 5 個tip_pct值:編寫一個函數,在指定列找出最大值,而後把這個值所在的行選取出來。

clipboard.png

smoker分組並用該分組函數調用apply,獲得:

clipboard.png

top函數在DataFrame的各個片斷上調用,而後結果由pandas.concat組裝到一塊兒,並以分組名稱進行了標記。

最後結果就有了一個層次化索引,其內層索引值來自原DataFrame

若是傳給apply的函數可以接受其餘參數或關鍵字,能夠將這些內容放在函數名後面一併傳入:

clipboard.png

GroupBy對象上調用describe

clipboard.png

GroupBy中,當調用如describe之類的方法時,實際上只是應用了下面兩條代碼的快捷方式:

clipboard.png

除這些基本用法以外,可否充分發揮apply的威力很大程度上取決於你的創造力,傳入的哪一個函數能作什麼全由你說了算,它只需返回一個pandas 對象標量值便可。


禁止分組鍵


分組鍵會跟原始對象的索引共同構成結果對象中的層次化索引,將group_keys=False傳入groupby便可禁止該效果:

clipboard.png

clipboard.png


分位數和桶分析


pandas有一些能根據指定面元或樣本分位數將數據拆分紅多塊的工具(cut 和 qcut),將這些函數跟groupby結合起來,就能很是輕鬆地實現對數據集的桶或分位數分析了。

  • 桶:bucket
  • 分位數:quantile

「長度相等的桶」指的是「區間大小相等」,「大小相等的桶」指的是「數據點數量相等」。

利用cut將其裝入長度相等的桶中:

clipboard.png

cut返回的Factor對象可直接用於groupby,能夠對data2作一些統計計算:

clipboard.png

要根據樣本分位數獲得大小相等的桶,使用qcut

clipboard.png

傳入labels=False,便可只獲取分位數的編號。不然那段仍是區間而不是編號:

clipboard.png


示例:用特定於分組的值填充缺失值


對於缺失數據的清理工做,有時用dropna將其濾除,有時則但願用一個固定值或由數據集自己所衍生出來的值去填充NA值,用fillna這個工具。

如用平均值去填充NA值

clipboard.png

對不一樣的分組填充不一樣的值:將數據分組,並使用apply和一個可以對各數據塊調用fillna的函數便可。

clipboard.png

用這個分組平均值去填充NA值

clipboard.png

也能夠在代碼中預約義各組的填充值,因爲分組具備一個name 屬性

clipboard.png

clipboard.png


示例:隨機採樣和排列


從一個大數據集中隨機抽取樣本以進行蒙特卡羅模擬(Monte Carlo simulation)或其餘分析工做。抽取的方式不少,其中的一些效率會比其餘的高不少

一個辦法是:選取np.random.permutation(N)的前K個元素,其中N爲完整數據的大小,K爲指望的樣本大小。

構造一副撲克牌:

clipboard.png

從整副牌中抽出 5 張:

clipboard.png

從每種花色中隨機抽取兩張牌,因爲花色是牌名的最後一個字符,能夠據此進行分組,並使用apply

clipboard.png

另外一種方法:

clipboard.png


示例:分組加權平均數和相關係數


例如對這個數據集利用category計算分組加權平均數:

clipboard.png

來自 Yahoo! Finance 的數據集:

圖片描述

計算一個由日收益率(經過百分數變化計算)與 SPX 之間的年度相關係數組成的DataFrame

clipboard.png

計算列於列之間的相關係數:(蘋果和微軟的年度相關係數)

clipboard.png


示例:面向分組的線性迴歸


仍是上個例子,定義下面這個regress函數(利用 statsmodels 庫)對各數據塊執行普通最小二乘法迴歸(Ordinary Least Squares, OLS)。

按年計算 AAPL 對 SPX 收益率的線性迴歸:

clipboard.png


透視表和交叉表

透視表(pivot table)


是各類電子表格程序和其餘數據分析軟件中一種常見的數據彙總工具。它根據一個或多個鍵對數據進行聚合,並根據行和列上的分組鍵將數據分配到各個矩形區域中。

在小費數據集中,根據daysmoker計算分組平均數(pivot_table 的默認聚合類型):

clipboard.png

只想聚合tip_pctsize,並根據day進行分組:

clipboard.png

傳入margins=True添加分項小計,將會添加標籤爲All的行和列,其值對應於單個等級中全部數據的分組統計。

clipboard.png

這裏All值爲平均數。

要使用其餘的聚合函數,將其傳給aggfunc便可。例如使用countlen獲得有關分組大小的交叉表:

clipboard.png

存在NA值,就設置一個fill_value

clipboard.png


交叉表(crosstab)


是一種用於計算分組頻率的特殊透視表。

clipboard.png

pandas.crosstab函數(pivot_table 也能實現該功能:根據 Nationality 和 Handedness 對這段數據進行彙總):

clipboard.png

crosstab的前兩個參數能夠是數組、Series、數組列表:

clipboard.png

示例:2012聯邦選舉委員會數據庫

加載數據

圖片描述

抽取有關贊助人和贊助模式的統計信息。

經過unique,能夠獲取所有的候選人名單:

clipboard.png

利用字典說明黨派關係:

clipboard.png

經過這個映射以及 Series對象的map方法,能夠根據候選人姓名獲得一組黨派信息:

clipboard.png

注意,該數據集既包括贊助也包括退款(負的出資額),爲了簡化分析過程,限定該數據集只能有正的出資額:

clipboard.png

因爲 Barack Obama 和 Mitt Romney 是最主要的兩名候選人,專門準備了一個子集,只包含針對他們兩人的競選活動的贊助信息:

clipboard.png

根據職業和僱主統計贊助信息

首先,根據職業計算出資總額:

clipboard.png

這裏只列出了前10個,注意到 許多職業都涉及相同的基本工做類型或同同樣東西有多種變體,清理一些這樣的數據:將一個職業信息映射到另外一個。

clipboard.png

對僱主信息也進行了一樣的處理。

這裏利用了dict.get,它容許沒有映射關係的職業也能「經過」。

如今,能夠經過pivot_table根據黨派和職業對數據進行聚合,而後過濾掉總出資額不足 200 萬美圓對數據:

clipboard.png

作成柱狀圖:

clipboard.png

對 Obama 和 Romney 總出資額最高的職業和企業:先對候選人進行分組,而後求取最大值:

clipboard.png

clipboard.png

對出資額分組

利用cut函數根據出資額的大小將數據離散化到多個面元中:

clipboard.png

clipboard.png

根據候選人姓名以及面元標籤對數據進行分組:

clipboard.png

對出資額求和並在面元內規格化,以便圖形化顯示兩位候選人各類贊助額度的比例:

clipboard.png

clipboard.png

clipboard.png

根據州統計贊助信息

首先,根據候選人和州對數據進行聚合:

clipboard.png

對各行除以總贊助額,就獲得各候選人在各州的總贊助額比例:

clipboard.png

clipboard.png


不足之處,歡迎指正。

相關文章
相關標籤/搜索