摘要:數據規整化清理轉換合并重塑數據聚合與分組運算數據規整化清理轉換合并重塑合并數據集可根據一個或多個鍵將不同中的行鏈接起來。函數根據樣本分位數對數據進行面元劃分。字典或,給出待分組軸上的值與分組名之間的對應關系。
本篇內容為整理《利用Python進行數據分析》,博主使用代碼為 Python3,部分內容和書本有出入。
在前幾篇中我們介紹了 NumPy、pandas、matplotlib 三個庫的基本操作,本篇介紹對數據的一些操作。
數據規整化:清理、轉換、合并、重塑
數據聚合與分組運算
pandas.merge:可根據一個或多個鍵將不同DataFrame中的行鏈接起來。
pandas.concat:可沿著一條軸將多個對象堆疊到一起。
combine_first:可將重復數據編接在一起,用一個對象中的值填充另一個對象中的缺失值。
數據庫風格的 DataFrame 合并
數據集的合并或連接運算:通過一個或多個鍵將行鏈接起來。
多對一的合并:
若沒有指定用哪個列進行連接,merge會將重疊列名當做鍵,指定如下:
若兩個對象的列名不同,可分別進行指定:
默認情況下,merge做inner連接,結果中的鍵是交集。外連接求取的是鍵的并集:
多對多的合并操作:
連接方式只影響出現在結果中的鍵。
根據多個鍵進行合并,傳入一個由列名組成的列表:
在進行列-列連接時,DataFrame對象中的索引會被丟棄。
suffixes選項:指定附加到左右兩個DataFrame對象的重疊列名上的字符串。
索引上的合并
當DataFrame中的連接鍵位于其索引中時,傳入left_index=True、 right_index=True,以說明索引應該被用作連接鍵:
對于層次化索引的數據:
必須以列表的形式指明用作合并鍵的列(注意對重復索引值的處理):
使用合并雙方的索引:
DataFrame的 join 實例方法:
更方便的實現按索引合并,不管有沒有重疊的列。在連接鍵上作左連接。
支持參數DataFrame的索引跟調用者DataFrame的某個列之間的連接:
對于簡單的索引合并,可以向join傳入一組DataFrame(concat 函數也是這個功能):
軸向連接
數據合并運算:
連接(concatenation)
綁定(binding)
堆疊(stacking)
NumPy有一個用于合并原始NumPy數組的concatenation函數:
pandas的concat函數:
默認情況下,concat在 axis=0 上工作,產生一個新Series。傳入 axis=1,產生一個DataFrame:
這種情況下,另外一條軸上沒有重疊,傳入 join = "inner" 得到它們的交集:
使用 key 參數,在連接軸上創建一個層次化索引:
沿著 axis=1 對Series進行合并,keys 就會成為DataFrame的列頭:
對DataFrame對象也是如此:
傳入一個字典,則字典的鍵會被當做keys選項的值:
用于管理層次化索引創建方式的參數:
跟當前分析工作無關的DataFrame行索引:
傳入 ignore_index = True:
合并重疊數據
關于有索引全部或部分重疊的兩個數據集。
NumPy的where函數,用于表達一種矢量化的if-else:
Series的combine_first方法,實現與上面一樣的功能,并會進行數據對齊:
對于DataFrame 一樣:
可以看作用參數對象中的數據為調用者對象的缺失數據“打補丁”。
用于重新排列表格型數據的基礎運算:重塑(reshape)或軸向旋轉(pivot)。
重塑層次化索引
stark:將數據的列“旋轉”為行
unstark:將數據的行“旋轉”為列
用stack方法將行轉為列,得到一個Series:
對層次化索引的Series,可以用unstack將其重新排為一個DataFrame:
默認情況下,unstack操作最內層。
傳入分層級別的編號或名稱可對其他級別進行unstack操作:
如果不是所有的級別值都能在各分組找到的話,unstack操作可能會引入缺失數據:
stack默認會濾除缺失數據,因此該運算是可逆的:
對DataFrame進行unstack操作時,作為旋轉軸的級別將會成為結果中的最低級別:
將“長格式”旋轉為“寬格式”
時間序列數據通常以 “長格式(long)”或“堆疊格式(stacked)”存儲在數據庫和 CSV 中。
轉成DataFrame,用 pivot 方法:
得到的DataFrame帶有層次化的列:
假設有兩個需要參與重塑的數據列:
pivot其實只是一個快捷方式:用set_index創建層次化索引,再用unstack重塑。
以上是數據的重排,下面是過濾、清理及其他轉換工作。
數據轉換移除重復數據
DataFrame中出現的重復行:
DataFrame的duplicated方法返回一個布爾型Series,表示各行是否是重復行,drop_duplicates方法返回一個移除了重復行的DataFrame:
指定部分列進行重復項判斷,如只希望根據k1列過濾重復項:
duplicated和drop_duplicates默認保留重復數值里第一次出現的組合,傳入keep = last則保留最后一個:
利用函數或映射進行數據轉換
根據數組、Series或DataFrame列中的值來實現轉換。
編寫一個肉類到動物的映射:
Series的map方法:可以接受一個函數或含有映射關系的字典型對象,用于修改對象的數據子集。
也可以傳入一個能夠完成全部這些工作的函數:
替換值
replace方法 :替換
利用fillna方法填充缺失數據可以看作替換的一種特殊情況。
替換一個值和一次性替換多個值:
對不同的值進行不同的替換:
傳入的參數也可以是字典:
重命名軸索引
軸標簽有一個map方法:
對函數或映射進行轉換,從而得到一個新對象。
將其值賦給index,就可以對DataFrame進行就地修改了:
要創建數據集的轉換版,而不是修改原始數據,用rename:
rename結合字典型對象可以實現對部分軸標簽的更新:
rename實現了復制DataFrame并對其索引和列標簽進行賦值,就地修改某個數據集,傳入inplace=True:
離散化和面元劃分
為了便于分析,連續數據常常被離散化或拆分為“面元(bin)”。
用pandas的cut函數:
pandas返回的是一個特殊的Categorical對象,它含有一個表示不同分類名稱的數組和一個為年齡數據進行標號的屬性:
哪邊是閉端可以通過right=False進行修改:
設置自己的面元名稱:
將labels選項設置為一個列表或數組即可。
如果向cut傳入的是面元的數量而不是確切的面元邊界,則它會根據數據的最小值和最大值計算等長面元:
將一些均勻分布的數據分成了四組。
qcut函數:根據樣本分位數對數據進行面元劃分。
由于qcut使用的是樣本分位數,可以得到大小基本相等的面元(而 cut 根據數據的分布情況,可能無法使各個面元中含有相同數量的數據點)。
設置自定義的分位數:
在聚合和分組運算時會再次用到cut 和 qcut 這兩個離散化函數。
檢測和過濾異常值
判斷是否存在異常值(outlier ):
找出某列中絕對值大小超過 3 的值:
選出全部含有“超過 3 或 -3 的值”的行:
將值限制在區間 -3 到 3 以內:
np.sign這個ufunc返回的是一個由 1 和 -1 組成的數組,表示原始值的符號。
排列和隨機采樣
numpy.random.permutation函數:對Series和DataFrame的列排列。
Permutation(5):需要排列的軸的長度。
然后就可以在基于ix的索引操作或take函數中使用該數組了:
選取隨機子集(非替換):
用替換的方式產生樣本:
計算指標/啞變量
將分類變量(Categorical)轉換為“啞變量矩陣(dummy matrix)”或“指標矩陣(indicator matrix)”。
給DataFrame的列加上一個前綴,以便能夠跟其他數據進行合并:
用get_dummies的prefix參數。
DataFrame中的某行同屬于多個分類的情況,舉個例子:
要為每個genre添加指標變量就需要做一些數據規整操作,構建多成員指標變量:
對于很大的數據,這種方式會變得非常慢,需要編寫一個能夠利用DataFrame內部機制的更低級的函數:
用get_dummies和cut之類的離散化函數。
字符串對象方法
Python 字符串對象的內置方法:
find找不到返回 -1,index找不到引發一個異常
傳入空字符串常常用于刪除模式:
正則表達式(regex)
提供了一種靈活的在文本中搜索或匹配字符串模式的方式。python 內置的re模塊負責對字符串應用正則表達式。
re模塊的函數分為三個大類:模式匹配、替換、拆分。
描述一個或多個空白符的regex是 s+。
調用re.split("s+", text)時,正則表達式會先被編譯,然后再在text上調用其split方法。
可以用re.compile自己編譯一個regex,以得到一個可重用的regex對象,如上所示。如果打算對許多字符串應用同一條正則表達式,強烈建議通過這種方法,可以節省大量的 CPU 時間。
得到匹配regex的所有模式:
findall:返回字符串中所有的匹配項。
search:只返回第一個匹配項。
match:只匹配字符串的首部。
sub方法:將匹配到的模式替換為指定字符串,并返回所得到的新字符串。
不僅想找出電子郵件地址,還想將各個地址分為 3 個部分,只需將待分段的模式的各部分用圓括號包起來:
通過groups方法返回一個由模式各段組成的元組。
對于帶有分組功能的模式,findall會返回一個元組列表:
sub還能通過諸如1, 2之類的特殊符號訪問各匹配項中的分組:
為各個匹配分組加上一個名稱,由這種正則表達式所產生的匹配對象可以得到一個簡單易用的帶有分組名稱的字典:
pandas 中矢量化的字符串函數
通過data.map,所有字符串和正則表達式方法都能被應用于各個值,但如存在NA就會報錯,為了解決這個問題,Series有一些能夠跳過NA值的字符串操作方法,通過Series的str屬性即可訪問這些方法:
也可以用正則表達式:
實現矢量化的元素獲取操作,對str.get/str屬性上使用索引:
對字符串進行子串截?。?/p>
對數據集進行分組并對各組應用一個函數。
在將數據集準備好之后,通常的任務就是計算分組統計或生成透視表。pandas提供了一個靈活高效的gruopby功能,對數據集進行切片、切塊、摘要等操作。
用 python 和pandas強大的表達能力可以執行復雜的多的分組運算:利用任何可以接受pandas對象或NumPy數組的函數。
分組運算:split(拆分)--apply(應用)--combine(合并)。
分組鍵的形式:
列表或數組,其長度與待分組的軸一樣。
表示DataFrame某個列名的值。
字典或Series,給出待分組軸上的值與分組名之間的對應關系。
函數,用于處理軸索引或索引中的各個標簽。
訪問data1,并根據key1調用groupby。
變量grouped是一個GroupBy對象,它實際上還沒有進行任何計算,只是含有一些有關分組鍵df["key1"]的中間數據。
例如,調用GroupBy的mean方法來計算分組平均值:
Series根據分組鍵進行了聚合,產生了一個新的Series,其索引為key1列中的唯一值。
通過兩個鍵對數據進行了分組后,得到的Series具有一個層次化索引:
分組鍵可以是任何長度適當的數組:
將列名用作分組鍵:
GroupBy的size方法返回一個含有分組大小的Series:
對分組進行迭代
GroupBy對象支持迭代,可以產生一組二元元組(由分組名和數據塊組成)。
對于多重鍵,元組的第一個元素將會是由鍵值組成的元組。
對數據片段進行操作,如將這些數據片段做成一個字典:
groupby默認在axis=0上進行分組,通過設置可以在其它任何軸上進行分組,如可以根據dtype對列進行分組:
選取一個或一組列
對于由DataFrame產生的GroupBy對象,用一個或一組(單個字符串或字符串數組)列名對其進行索引,就能實現選取部分列進行聚合的目的:
例如,對部分列進行聚合:計算data2列的平均值并以DataFrame形式得到結果:
返回一個已分組的DataFrame(傳入的是列表或數組)或Series(傳入的是標量形式的單個列名):
通過字典或 Series 進行分組
除數組以外,分組信息還可以其他形式存在
根據分組計算列的sum:
將mapping這個字典傳給groupby即可。
用Series作為分組鍵:
這里Series可以被看做一個固定大小的映射。pandas會檢查Series以確保其索引根分組軸是對齊的。
通過函數進行分組
任何被當做分組鍵的函數都會在各個索引值上被調用一次,其返回值就會被用作分組名稱。
將函數根數組、列表、字典、Series混合使用(任何東西最終都會被轉換為數組):
Key_list和人名對應,再在相同長度的對應一列里選min的值。
根據索引級別分組
層次化索引數據集通過level關鍵字傳入級別編號或名稱:
可以使用經過優化的GroupBy的方法,還可以使用自己發明的聚合運算,還可以調用分組對象上已經定義好的任何方法,如 quantile可以計算Series或DataFrame列的樣本分位數:
GroupBy會高效地對Series進行切片,然后對各片調用piece.quantile(0.9),最后將這些結果組裝成最終結果。
使用自己的聚合函數,傳入aggregate或agg方法即可:
有些方法如describe也可以用,但嚴格來講它們并非聚合運算。
自定義聚合函數比表中的經過優化的函數慢得多,這是因為在構造中間分組數據塊時存在非常大的開銷(函數調用、數據重排等)。
面向列的多函數應用
根據 "smoker" 和 "size" 對 tips 進行分組:
傳入一組函數或函數名,得到的DataFrame的列就會以相應的函數命名:
傳入一個由(name, function )元組組成的列表,各元組的第一個元素會被用作DataFrame的列名:
對于DataFrame,定義一組應用于全部列的函數,或不同的列應用不同的函數。
結果的DataFrame擁有層次化的列。相當于分別對列["tip_pct"]和列["total_bill"]進行聚合,然后用concat將結果組裝到一起(列名用作 keys 參數)。
傳入帶有自定義名稱的元組列表:
對不同的列應用不同的函數:向agg傳入一個從列名映射到函數的字典
只有將多個函數應用到至少一列時,DataFrame才會擁有層次化的列:
以“無索引”的形式返回聚合數據
向groupby傳入as_index=False,禁用功能由唯一的分組鍵組成索引:
聚合只是分組運算的其中一種,它接受能夠將一維數據簡化為標量值的函數。
接下來介紹 transform 和 apply 方法,執行更多其他的分組運算。
為一個DataFrame添加一個用于存放各索引分組平均值的列:先聚合再合并。
下面在GroupBy上使用transform方法:
transform會將一個函數應用到各個分組,然后將結果放置到適當的位置上。
從各組中減去平均值:先創建一個距平化函數(demeaning function),然后將其傳給transform。
檢查demeaned現在的分組平均值是否為 0:
跟aggregate一樣,transform也是一個有著嚴格條件的特殊函數,傳入的函數只能產生兩種結果,一個可以廣播的標量值(如 np.mean) 或一個相同大小的結果數組。
apply:一般性的“拆分-應用-合并”
最一般化的GroupBy方法是apply:apply會將待處理的對象拆分成多個片段,然后對各片段調用傳入的函數,最后嘗試將各片段組合到一起。
根據分組選出最高的 5 個tip_pct值:編寫一個函數,在指定列找出最大值,然后把這個值所在的行選取出來。
對smoker分組并用該分組函數調用apply,得到:
top函數在DataFrame的各個片段上調用,然后結果由pandas.concat組裝到一起,并以分組名稱進行了標記。
最后結果就有了一個層次化索引,其內層索引值來自原DataFrame。
如果傳給apply的函數能夠接受其他參數或關鍵字,可以將這些內容放在函數名后面一并傳入:
在GroupBy對象上調用describe:
在GroupBy中,當調用如describe之類的方法時,實際上只是應用了下面兩條代碼的快捷方式:
除這些基本用法之外,能否充分發揮apply的威力很大程度上取決于你的創造力,傳入的哪個函數能做什么全由你說了算,它只需返回一個pandas 對象或標量值即可。
禁止分組鍵
分組鍵會跟原始對象的索引共同構成結果對象中的層次化索引,將group_keys=False傳入groupby即可禁止該效果:
分位數和桶分析
pandas有一些能根據指定面元或樣本分位數將數據拆分成多塊的工具(cut 和 qcut),將這些函數跟groupby結合起來,就能非常輕松地實現對數據集的桶或分位數分析了。
桶:bucket
分位數:quantile
“長度相等的桶”指的是“區間大小相等”,“大小相等的桶”指的是“數據點數量相等”。
利用cut將其裝入長度相等的桶中:
由cut返回的Factor對象可直接用于groupby,可以對data2做一些統計計算:
要根據樣本分位數得到大小相等的桶,使用qcut:
傳入labels=False,即可只獲取分位數的編號。否則那段還是區間而不是編號:
示例:用特定于分組的值填充缺失值
對于缺失數據的清理工作,有時用dropna將其濾除,有時則希望用一個固定值或由數據集本身所衍生出來的值去填充NA值,用fillna這個工具。
如用平均值去填充NA值:
對不同的分組填充不同的值:將數據分組,并使用apply和一個能夠對各數據塊調用fillna的函數即可。
用這個分組平均值去填充NA值:
也可以在代碼中預定義各組的填充值,由于分組具有一個name 屬性:
示例:隨機采樣和排列
從一個大數據集中隨機抽取樣本以進行蒙特卡羅模擬(Monte Carlo simulation)或其他分析工作。抽取的方式很多,其中的一些效率會比其他的高很多
一個辦法是:選取np.random.permutation(N)的前K個元素,其中N為完整數據的大小,K為期望的樣本大小。
構造一副撲克牌:
從整副牌中抽出 5 張:
從每種花色中隨機抽取兩張牌,由于花色是牌名的最后一個字符,可以據此進行分組,并使用apply:
另一種方法:
示例:分組加權平均數和相關系數
例如對這個數據集利用category計算分組加權平均數:
來自 Yahoo! Finance 的數據集:
計算一個由日收益率(通過百分數變化計算)與 SPX 之間的年度相關系數組成的DataFrame:
計算列于列之間的相關系數:(蘋果和微軟的年度相關系數)
示例:面向分組的線性回歸
還是上個例子,定義下面這個regress函數(利用 statsmodels 庫)對各數據塊執行普通最小二乘法回歸(Ordinary Least Squares, OLS)。
按年計算 AAPL 對 SPX 收益率的線性回歸:
透視表(pivot table)
是各種電子表格程序和其他數據分析軟件中一種常見的數據匯總工具。它根據一個或多個鍵對數據進行聚合,并根據行和列上的分組鍵將數據分配到各個矩形區域中。
在小費數據集中,根據day和smoker計算分組平均數(pivot_table 的默認聚合類型):
只想聚合tip_pct和size,并根據day進行分組:
傳入margins=True添加分項小計,將會添加標簽為All的行和列,其值對應于單個等級中所有數據的分組統計。
這里All值為平均數。
要使用其他的聚合函數,將其傳給aggfunc即可。例如使用count或len得到有關分組大小的交叉表:
存在NA值,就設置一個fill_value:
交叉表(crosstab)
是一種用于計算分組頻率的特殊透視表。
用pandas.crosstab函數(pivot_table 也能實現該功能:根據 Nationality 和 Handedness 對這段數據進行匯總):
crosstab的前兩個參數可以是數組、Series、數組列表:
示例:2012聯邦選舉委員會數據庫加載數據
抽取有關贊助人和贊助模式的統計信息。
通過unique,可以獲取全部的候選人名單:
利用字典說明黨派關系:
通過這個映射以及 Series對象的map方法,可以根據候選人姓名得到一組黨派信息:
注意,該數據集既包括贊助也包括退款(負的出資額),為了簡化分析過程,限定該數據集只能有正的出資額:
由于 Barack Obama 和 Mitt Romney 是最主要的兩名候選人,專門準備了一個子集,只包含針對他們兩人的競選活動的贊助信息:
根據職業和雇主統計贊助信息
首先,根據職業計算出資總額:
這里只列出了前10個,注意到 許多職業都涉及相同的基本工作類型或同一樣東西有多種變體,清理一些這樣的數據:將一個職業信息映射到另一個。
對雇主信息也進行了同樣的處理。
這里利用了dict.get,它允許沒有映射關系的職業也能“通過”。
現在,可以通過pivot_table根據黨派和職業對數據進行聚合,然后過濾掉總出資額不足 200 萬美元對數據:
做成柱狀圖:
對 Obama 和 Romney 總出資額最高的職業和企業:先對候選人進行分組,然后求取最大值:
對出資額分組
利用cut函數根據出資額的大小將數據離散化到多個面元中:
根據候選人姓名以及面元標簽對數據進行分組:
對出資額求和并在面元內規格化,以便圖形化顯示兩位候選人各種贊助額度的比例:
根據州統計贊助信息
首先,根據候選人和州對數據進行聚合:
對各行除以總贊助額,就得到各候選人在各州的總贊助額比例:
不足之處,歡迎指正。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44765.html
摘要:中面向行和面向列的操作基本是平衡的。用層次化索引,將其表示為更高維度的數據。使用浮點值表示浮點和非浮點數組中的缺失數據。索引的的格式化輸出形式選取數據子集在內層中進行選取層次化索引在數據重塑和基于分組的操作中很重要。 我們在上一篇介紹了 NumPy,本篇介紹 pandas。 pandas入門 Pandas 是基于Numpy構建的,讓以NumPy為中心的應用變的更加簡單。 pandas...
摘要:提供了使我們能夠快速便捷地處理結構化數據的大量數據結構和函數。結構化數據,例如多維數據矩陣表格行數據,其中各列可能是不同的類型字符串數值日期等?;A數組和矢量計算高性能科學計算和數據分析的基礎包。 本篇內容為整理《利用Python進行數據分析》,博主使用代碼為 Python3,部分內容和書本有出入。 利用 Python 進行科學計算的實用指南。本書重點介紹了用于高效解決各種數據分析問...
摘要:有一些表示常見圖形的對象稱為塊,完整的集合位于。中的繪圖函數在中,有行標簽列標簽分組信息。密度圖通過計算可能會產生觀測數據的連續概率分布的估計而產生的。在探索式數據分析工作中,同時觀察一組變量的散布圖是很有意義的。 我們在上一篇介紹了 pandas,本篇介紹 matplotlib。 繪圖和可視化 一個用于創建出版質量圖表的桌面繪圖包。 Matplotlib API入門 Figure ...
摘要:全棧數據之門前言自強不息,厚德載物,自由之光,你是我的眼基礎,從零開始之門文件操作權限管理軟件安裝實戰經驗與,文本處理文本工具的使用家族的使用綜合案例數據工程,必備分析文件探索內容探索交差并補其他常用的命令批量操作結語快捷鍵,之門提高效率光 showImg(https://segmentfault.com/img/bVK0aK?w=350&h=350); 全棧數據之門 前言 自強不息,...
閱讀 1768·2021-10-11 10:57
閱讀 2352·2021-10-08 10:14
閱讀 3393·2019-08-29 17:26
閱讀 3340·2019-08-28 17:54
閱讀 3020·2019-08-26 13:38
閱讀 2884·2019-08-26 12:19
閱讀 3608·2019-08-23 18:05
閱讀 1277·2019-08-23 17:04