Pandas 不擅長的結構化數據運算

Pandas 是 python 的一個數據分析包,是基於 NumPy 的一種數據分析工具,其中歸入了大量庫和一些標準的數據模型,提供了快速便捷地處理數據的函數和方法,是高效地操做結構化數據集所需的工具,也是使 Python 成爲強大而高效的數據分析環境的重要因素之一。python

可是相信常用 Pandas 的同窗在處理結構化數據運算時也會遇到一些麻煩,這些問題要麼使得問題解決很複雜(代碼難寫),要麼使得運行極其緩慢(效率低下),下面總結整理了一些 Pandas 的困難問題進行吐槽,若有謬誤歡迎指正,也歡迎你們參加到此次的「Pandas 吐槽大會」。程序員

切片賦值

切片賦值,指取數據中的某個值或某一塊值,修改其中的值,如把第 3 行第 5 列的 x 值修改成 y 值。數組

使用員工信息數據做爲案例進行介紹,數據片斷以下:多線程

1png

問題一:將R&D 部門員工的工資改爲 20000函數

Python 代碼工具

2png

運行結果:大數據

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 進行修改,這樣不只能夠獲得正確的結果,並且也能夠解決報警的問題。

代碼修改以下:

3png

運行結果:

..

這纔是 Pandas 解決問題的方案。

討論:問題的實質是咱們想經過修改視圖修改源數據。而 data\[data\['DEPT'\]=='R&D'\]\['SALARY'\]=2000 是將兩個索引操做連接在一塊兒,即直接使用了兩次方括號的鏈式索引。

  1. data\[data\['DEPT'\]=='R&D'\]
  2. \['SALARY'\]=20000

以上兩個鏈式操做一個接一個地獨立執行。第一次鏈式操做是爲了 Get,返回一個 DataFrame,其中包含全部 DEPT 等於 'R&D' 的行;第二次鏈式操做是爲了 Set,是在這個新返回的 DataFrame 上運行的,並無修改原始的 DataFrame。而此時使用 loc 函數得到原 DataFrame 的視圖,在視圖上賦值就能夠修改原始 DataFrame 的值。

這種問題仍是比較容易發現的,下面再來看一種狀況:

問題二:修改 R&D 部門 5 號員工的工資爲 19950

問題分析:在實際的工做中,常常把視圖賦值給某個變量進行後續的計算,直到某一步,又想修改其中的某行的值,此時再使用 loc 函數時也會出現 SettingWithCopyWarning

Python 代碼:

4png

運行結果:

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 號員工的工資。

代碼以下:

5png

運行結果:

..

討論:var=df.copy() 是明確的告知此 var 是 DataFrame 的副本,此時再使用 loc 函數賦值時,就避免了兩次鏈式索引,也就避免了 SettingWithCopyWarning 的警告。

Pandas 針對 df 的操做冷不防就會產生視圖,賦值時會錯位,同時也會浪費時間。

集合運算

常見的集合運算,包括交集,差集,並集,異或集和和集運算,下面來看下 Pandas 兩個集合間的運算。

問題三:求銷售部門的員工與女員工的交集,差集,並集,異或集和和集。

Python 代碼:

6png

討論:Pandas 集合運算時,只能對着索引進行,而後再從原始數據中按索引截取獲得結果。DataFrame 不能夠直接進行集合運算。並且當集合數多於兩個時,須要經過循環兩兩計算獲得結果,再從原始數據按索引截取。 當但願按照某列進行集合運算時,則還須要把該列轉成索引,計算完成後還要重置索引,獲得結果。對於簡單的集合運算看起來就很麻煩,若是 Pandas 能支持集合 (set) 數據類型的集合運算,經過符號 (&-|^) 進行運算就行了。

聚合運算

Pandas 提供了不少聚合運算函數,好比求和 sum(),平均 mean(),計數 count(),方差 var(),標準差 std() 等等。但遇到稍微特殊一點聚合運算時就有點麻煩,請看如下兩個問題。

問題四:查看全部工資最高的員工的信息

問題分析:首先找到最高工資,再篩選出等於最高工資的員工。

Python 代碼:

7png

討論:這種方式須要遍歷兩邊數據,計算最大值時一遍,過濾時一遍,效率比較低。有一種方式能夠只遍歷一遍。即找最大值的同時記錄下最大值員工的索引,而後直接利用索引取數就能夠了。但是 Pandas 的 idxmax() 函數只返回一個最大值的索引,不能夠返回所有最大值的索引,所以就只能用上邊的笨方法來解決這個問題。

問題五:找到年齡最大的 5 位員工,即 TOPN 問題。

問題分析:最大值是至關於 TOP1,所以 TOPN 問題也至關於聚合運算。

Python 代碼:

8png

討論:TOPN 問題並不須要大排序,只須要維護一個 N 長度的序列便可,保持序列中的 N 個數老是遍歷過的數據中的最大值或者最小值便可。你們都知道大排序的效率是很低的,並且當數據量很大時,大排序複雜度和效率又會進一步惡化。但 Pandas 並無提供高效的計算函數。即便是 nlargest()和 nsmallest() 函數底層也是大排序後取前五。

定位計算

Pandas 提供了索引功能,用戶可使用索引進行切片等操做,但當遇到須要計算指定索引(即位置)比前一行的行就比較麻煩,以下面這個問題:

問題六:計算股價超過 100 的交易日的當日漲幅

問題分析:須要篩選出股價超過 100 的交易日的交易信息,將數據提早一天,使用相同的索引截取兩份數據,計算二者的漲幅。

Python 代碼:

9png

討論:Python 並無提供利用位置進行相關計算的函數,因此計算這類問題就略顯麻煩。

分組運算

Pandas 提供了豐富的分組運算,既能夠按照列名分組,也能夠按照指定的數組分組,既能夠對單列使用多種方式聚合,也能夠對多列聚合,還能夠循環各組,處理分組之後的集合。但有一些常見的分組運算使用 Pandas 作起來要麼比較繁瑣,要麼效率低下。

好比按位置分組、值變化分組、條件變化分組都須要衍生出一個數組做爲分組依據,對位分組則須要使用 left join 的方式來繞,枚舉分組更是須要屢次分組,篩選須要的分組再合併,這裏有一篇文章詳細介紹了 Pandas 分組運算的一些例子

Python 分組處理

你們能夠經過具體的例子體會 Pandas 分組的不便之處。

並行運算

Pandas 並不提供並行計算的方法,這也是 Pandas 被詬病最多的一方面,而 Python 所謂的多線程對於 CPU 而言仍是單線程。

大數據計算

Pandas 雖然可使用分段讀取的方式來獲取數據,但想要實現一些複雜的運算,好比排序、分組、關聯等等都會很是很是麻煩,並且對程序員的技術要求也會很高。詳細論述能夠查看另外一篇文檔。

Python 如何處理大文件

相關文章
相關標籤/搜索