Pandas 是 python 的一個數據分析包,是基於 NumPy 的一種數據分析工具,其中歸入了大量庫和一些標準的數據模型,提供了快速便捷地處理數據的函數和方法,是高效地操做結構化數據集所需的工具,也是使 Python 成爲強大而高效的數據分析環境的重要因素之一。python
可是相信常用 Pandas 的同窗在處理結構化數據運算時也會遇到一些麻煩,這些問題要麼使得問題解決很複雜(代碼難寫),要麼使得運行極其緩慢(效率低下),下面總結整理了一些 Pandas 的困難問題進行吐槽,若有謬誤歡迎指正,也歡迎你們參加到此次的「Pandas 吐槽大會」。程序員
切片賦值,指取數據中的某個值或某一塊值,修改其中的值,如把第 3 行第 5 列的 x 值修改成 y 值。數組
使用員工信息數據做爲案例進行介紹,數據片斷以下:多線程
問題一:將R&D 部門員工的工資改爲 20000函數
Python 代碼工具
運行結果:大數據
SettingWithCopyWarning:spa
A value is trying to be set on a copy of a slice from a DataFrame.線程
Try using .loc\[row\_indexer,col\_indexer\] = value instead3d
能夠看到,報了這個 SettingWithCopyWarning,並且修改的值並無起做用。相信這個問題對於大多數的 Pandas 用戶並不陌生,那麼怎麼修改呢?
就像 SettingWithCopyWarning 中提示的那樣,使用 df.loc\[row\_indexer,col\_indexer\] = value 進行修改,這樣不只能夠獲得正確的結果,並且也能夠解決報警的問題。
代碼修改以下:
運行結果:
這纔是 Pandas 解決問題的方案。
討論:問題的實質是咱們想經過修改視圖修改源數據。而 data\[data\['DEPT'\]=='R&D'\]\['SALARY'\]=2000 是將兩個索引操做連接在一塊兒,即直接使用了兩次方括號的鏈式索引。
以上兩個鏈式操做一個接一個地獨立執行。第一次鏈式操做是爲了 Get,返回一個 DataFrame,其中包含全部 DEPT 等於 'R&D' 的行;第二次鏈式操做是爲了 Set,是在這個新返回的 DataFrame 上運行的,並無修改原始的 DataFrame。而此時使用 loc 函數得到原 DataFrame 的視圖,在視圖上賦值就能夠修改原始 DataFrame 的值。
這種問題仍是比較容易發現的,下面再來看一種狀況:
問題二:修改 R&D 部門 5 號員工的工資爲 19950
問題分析:在實際的工做中,常常把視圖賦值給某個變量進行後續的計算,直到某一步,又想修改其中的某行的值,此時再使用 loc 函數時也會出現 SettingWithCopyWarning
Python 代碼:
運行結果:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc\[row\_indexer,col\_indexer\] = value instead
觀察發現,即便使用了 loc 函數,當再次使用 loc 函數時,仍是會出現 SettingWithCopyWarning 的報警,其中的緣由仍是將兩個索引操做連接在一塊兒,第一次爲 get,第二次爲 set。此次所不一樣的是賦值結果起做用了,獲得了咱們指望的結果。但咱們也不該該忽略此 Warning,而是應該明確的告訴 Pandas 變量 r_d 是 data 中截取視圖的副本,而後再使用 loc 函數修改 5 號員工的工資。
代碼以下:
運行結果:
討論:var=df.copy() 是明確的告知此 var 是 DataFrame 的副本,此時再使用 loc 函數賦值時,就避免了兩次鏈式索引,也就避免了 SettingWithCopyWarning 的警告。
Pandas 針對 df 的操做冷不防就會產生視圖,賦值時會錯位,同時也會浪費時間。
常見的集合運算,包括交集,差集,並集,異或集和和集運算,下面來看下 Pandas 兩個集合間的運算。
問題三:求銷售部門的員工與女員工的交集,差集,並集,異或集和和集。
Python 代碼:
討論:Pandas 集合運算時,只能對着索引進行,而後再從原始數據中按索引截取獲得結果。DataFrame 不能夠直接進行集合運算。並且當集合數多於兩個時,須要經過循環兩兩計算獲得結果,再從原始數據按索引截取。 當但願按照某列進行集合運算時,則還須要把該列轉成索引,計算完成後還要重置索引,獲得結果。對於簡單的集合運算看起來就很麻煩,若是 Pandas 能支持集合 (set) 數據類型的集合運算,經過符號 (&-|^) 進行運算就行了。
Pandas 提供了不少聚合運算函數,好比求和 sum(),平均 mean(),計數 count(),方差 var(),標準差 std() 等等。但遇到稍微特殊一點聚合運算時就有點麻煩,請看如下兩個問題。
問題四:查看全部工資最高的員工的信息
問題分析:首先找到最高工資,再篩選出等於最高工資的員工。
Python 代碼:
討論:這種方式須要遍歷兩邊數據,計算最大值時一遍,過濾時一遍,效率比較低。有一種方式能夠只遍歷一遍。即找最大值的同時記錄下最大值員工的索引,而後直接利用索引取數就能夠了。但是 Pandas 的 idxmax() 函數只返回一個最大值的索引,不能夠返回所有最大值的索引,所以就只能用上邊的笨方法來解決這個問題。
問題五:找到年齡最大的 5 位員工,即 TOPN 問題。
問題分析:最大值是至關於 TOP1,所以 TOPN 問題也至關於聚合運算。
Python 代碼:
討論:TOPN 問題並不須要大排序,只須要維護一個 N 長度的序列便可,保持序列中的 N 個數老是遍歷過的數據中的最大值或者最小值便可。你們都知道大排序的效率是很低的,並且當數據量很大時,大排序複雜度和效率又會進一步惡化。但 Pandas 並無提供高效的計算函數。即便是 nlargest()和 nsmallest() 函數底層也是大排序後取前五。
Pandas 提供了索引功能,用戶可使用索引進行切片等操做,但當遇到須要計算指定索引(即位置)比前一行的行就比較麻煩,以下面這個問題:
問題六:計算股價超過 100 的交易日的當日漲幅
問題分析:須要篩選出股價超過 100 的交易日的交易信息,將數據提早一天,使用相同的索引截取兩份數據,計算二者的漲幅。
Python 代碼:
討論:Python 並無提供利用位置進行相關計算的函數,因此計算這類問題就略顯麻煩。
Pandas 提供了豐富的分組運算,既能夠按照列名分組,也能夠按照指定的數組分組,既能夠對單列使用多種方式聚合,也能夠對多列聚合,還能夠循環各組,處理分組之後的集合。但有一些常見的分組運算使用 Pandas 作起來要麼比較繁瑣,要麼效率低下。
好比按位置分組、值變化分組、條件變化分組都須要衍生出一個數組做爲分組依據,對位分組則須要使用 left join 的方式來繞,枚舉分組更是須要屢次分組,篩選須要的分組再合併,這裏有一篇文章詳細介紹了 Pandas 分組運算的一些例子
你們能夠經過具體的例子體會 Pandas 分組的不便之處。
Pandas 並不提供並行計算的方法,這也是 Pandas 被詬病最多的一方面,而 Python 所謂的多線程對於 CPU 而言仍是單線程。
Pandas 雖然可使用分段讀取的方式來獲取數據,但想要實現一些複雜的運算,好比排序、分組、關聯等等都會很是很是麻煩,並且對程序員的技術要求也會很高。詳細論述能夠查看另外一篇文檔。