第89天:NumPy 排序和篩選函數

2021-03-02 Python技術

對於數據分析來說,排序和篩選數據是不可或缺的一部分內容。NumPy 也提供了多種排序和篩選函數,本文就來介紹一下 NumPy 常見的排序和篩選函數。

排序函數

NumPy 中提供了排序相關的函數。排序函數已經幫助我們實現了不同的排序算法,我們只需要拿來直接使用就行。每個排序算法的執行速度,時間複雜度,空間複雜度和算法的穩定性都不相同,我們來看看常見的幾種排序算法的比較。

排序算法速度時間複雜度空間複雜度穩定性quicksort(快速排序)1o(n^2)0否mergesort(歸併排序)2O(n*log(n))~n/2是heapsort(堆排序)3O(n*log(n))0否numpy.sort(a, axis, kind, order)

這個排序函數有4個參數,我們來看看參數的說明:

參數說明a要排序的數組axis排序數組的軸,如果沒有數組會被展開,沿著最後的軸排序。axis=0 按列排序,axis=1 按行排序kind排序類型,有 quicksort 、mergesort 、heapsort 、stable 幾種,默認為quicksort(快速排序)order排序的欄位,針對包含欄位的數組

我們來看看實例:

import numpy as npimport time
a = np.array([[3, 7, 12, 45], [9, 1, 0, 34]])print("初始數組:")print(a)print('\n')
print(np.char.center('調用 sort() 函數,默認快速排序', 15, '*'))print(np.sort(a))print('\n')
print(np.char.center('按列排序', 15, '*'))print(np.sort(a, axis=0))print('\n')
b = np.random.randint(1, 1000, size=[10000, 10000])
print(np.char.center('快速排序時間', 15, '*'))t1 = time.time()np.sort(b)t2 = time.time()print(t2 - t1)print('\n')
print(np.char.center('堆排序時間', 15, '*'))t3 = time.time()np.sort(b, -1, 'heapsort')t4 = time.time()print(t4 - t3)print('\n')
print(np.char.center('歸併排序時間', 15, '*'))t5 = time.time()np.sort(b, -1, 'mergesort')t6 = time.time()print(t6 - t5)print('\n')
# 根據欄位排序dt = np.dtype([('name', 'S10'), ('age', int)])c = np.array([("raju", 21), ("anil", 25), ("ravi", 17), ("amar", 27)], dtype=dt)print(np.char.center('根據欄位排序的數組', 15, '*'))print(c)print('\n')
print(np.char.center('按 name 排序', 15, '*'))print(np.sort(c, order='name'))
# 返回初始數組:[[ 3 7 12 45] [ 9 1 0 34]] 調用 sort() 函數,默認[[ 3 7 12 45] [ 0 1 9 34]] ******按列排序*****[[ 3 1 0 34] [ 9 7 12 45]] *****快速排序時間****5.470074892044067
*****堆排序時間*****6.988600015640259
*****歸併排序時間****5.784327983856201
***根據欄位排序的數組***[(b'raju', 21) (b'anil', 25) (b'ravi', 17) (b'amar', 27)]
***按 name 排序***[(b'amar', 27) (b'anil', 25) (b'raju', 21) (b'ravi', 17)]

在例子中,我們首先使用了默認的按橫軸的快速排序算法,可以看到每個數組都是橫向排序的。

接下來,我們多加了一個排序的參數,表示按縱軸排序,我們可以從結果中看到,兩個數組中對應位置的元素都按照升序排列了。

接著我們隨機生成了一個數據量大的多維數組,然後使用三種排序方式,列印了它們排序的時間,從結果中我們可以看到快速排序最快,其次是歸併排序,最後是堆排序。需要注意一點的是,有些排序算法不穩定,可能會導致每次運行的結果不一樣。另外,數據量也可能會影響不同排序算法排序的效率。

最後我們創建了一個帶欄位的數組,然後按照 name 欄位排序。

numpy.argsort()

函數對輸入數組沿給定軸執行間接排序,並使用指定排序類型返回數據的索引數組。這個索引數組用於構造排序後的數組。

我們來看實例:

import numpy as np
a = np.array([3, 4, 2])print("初始數組:")print(a)print('\n')
print(np.char.center('調用 argsort() 函數', 15, '*'))b = np.argsort(a)print(b)print('\n')
print(np.char.center('以排序後的順序重構原數組', 15, '*'))print(a[b])print('\n')
# 返回初始數組:[3 4 2]
調用 argsort() 函數[2 0 1]
**以排序後的順序重構原數組*[2 3 4]

在上面例子中,我們調用 argsort() 函數後,返回了初始數組的排序後的索引。然後我們用排序後的索引數組重構原數組,得到排序後的數組。

numpy.lexsort()

函數使用鍵序列執行間接排序。鍵可以看作是電子表格中的一列。該函數返回一個索引數組,使用它可以獲得排序數據。注意,最後一個鍵恰好是 sort 的主鍵。

對於這個函數,我們假設一種場景:現在有語文和數學考試成績以及總成績,我們需要對成績做個排序,排序原則為總分優先,總分相同則語文高的排前面。

實現的代碼如下:

import numpy as np
print(np.char.center('lexsort() 函數', 15, '*'))# 錄入了四位同學的成績math = (10, 20, 50, 10)chinese = (30, 50, 40, 60)total = (40, 70, 90, 70)# 將優先級高的項放在後面ind = np.lexsort((math, chinese, total))
for i in ind: print(total[i], chinese[i], math[i]) # 返回**lexsort() 函數*40 30 1070 50 2070 60 1090 40 50

例子中我們將參數由優先級從低到高傳入,優先級最高的放在最後。最後得到4個同學的成績排序。

numpy.msort()

數組按第一個軸排序,返回排序後的數組副本。

這個排序相當於 numpy.sort(a, axis=0)。很好理解。我們直接來看實例:

import numpy as np
print(np.char.center('msort() 函數', 20, '*'))msa = np.array([[3, 7, 12, 45], [9, 1, 0, 34]])print(np.msort(msa))
# 返回*****msort() 函數*****[[ 3 1 0 34] [ 9 7 12 45]]

numpy.partition()

指定一個數,對數組進行分區。

通俗點說,就是指定一個數,以這個數為中心,將其他數分別放在這個數的兩邊。

我們來看實例:

import numpy as np
print(np.char.center('partition() 函數', 20, '*'))pta = np.array([3, 7, 12, 45, 15, 0])print(np.partition(pta, 2))print('\n')print(np.partition(pta, (2, 4)))print('\n')
# 返回***partition() 函數***[ 0 3 7 45 15 12][ 0 3 7 12 15 45]

在第一次排序時,我們選中了索引為2的數字7作為中心,將小於7的數放在左邊,大於7的數放在右邊。在第二次排序時,我們選擇了索引為2的數字7和索引為4的數字45,將小於7的數放在左邊,大於7小於45的數放在中間,大於45的數放在右邊。

查找函數

下面我們來看幾個常見的查找函數,這些函數用於在數組中查找特定條件的元素。

numpy.argmax()

返回沿給定軸的最大值索引。

注意,索引的值是從0開始計算的。

我們來看實例:

import numpy as np
a = np.array([[30, 40, 70], [80, 20, 10], [50, 90, 60]])print(np.char.center('初始數組', 20, '*'))print(a)print('\n')
print(np.char.center('調用 argmax() 函數', 20, '*'))print(np.argmax(a))print('\n')
print(np.char.center('展開數組', 20, '*'))print(a.flatten())print('\n')
print(np.char.center('沿0軸的最大索引', 20, '*'))print(np.argmax(a, 0))print('\n')
print(np.char.center('沿1軸的最大索引', 20, '*'))print(np.argmax(a, 1))print('\n')
# 返回********初始數組********[[30 40 70] [80 20 10] [50 90 60]]***調用 argmax() 函數***7********展開數組********[30 40 70 80 20 10 50 90 60]******沿0軸的最大索引******[1 2 0]******沿1軸的最大索引******[2 0 1]

numpy.argmin()

返回沿給定軸的最小值索引。

注意,索引的值是從0開始計算的。

我們來看實例:

import numpy as np
a = np.array([[30, 40, 70], [80, 20, 10], [50, 90, 60]])print(np.char.center('初始數組', 20, '*'))print(a)print('\n')
print(np.char.center('調用 argmin() 函數', 20, '*'))print(np.argmin(a))print('\n')
print(np.char.center('沿0軸的最小索引', 20, '*'))print(np.argmin(a, 0))print('\n')
print(np.char.center('沿1軸的最小索引', 20, '*'))print(np.argmin(a, 1))print('\n')
# 返回********初始數組********[[30 40 70] [80 20 10] [50 90 60]]***調用 argmin() 函數***5******沿0軸的最小索引******[0 1 1]******沿1軸的最小索引******[0 2 0]

numpy.nonzero()

返回輸入數組中非零元素的索引。

只有a中非零元素才會有索引值,那些零值元素沒有索引值;返回的索引值數組是一個2維tuple數組,該tuple數組中包含一維的array數組。其中,一維array向量的個數與a的維數是一致的。索引值數組的每一個array均是從一個維度上來描述其索引值。比如,如果a是一個二維數組,則索引值數組有兩個array,第一個 array 從行維度來描述索引值;第二個array從列維度來描述索引值。該np.transpose(np.nonzero(x)) 函數能夠描述出每一個非零元素在不同維度的索引值。

我們來看實例:

import numpy as np
b = np.array([[30, 40, 0], [0, 20, 10], [50, 0, 60]])print(np.char.center('我們的數組是', 20, '*'))print(b)print(np.char.center('調用 nonzero() 函數', 20, '*'))c = np.nonzero(b)print(c)print(np.transpose(np.nonzero(b)))
# 返回*******我們的數組是*******[[30 40 0] [ 0 20 10] [50 0 60]]**調用 nonzero() 函數***(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 0, 2]))[[0 0] [0 1] [1 1] [1 2] [2 0] [2 2]]

我們通過 np.transpose() 方法轉換後看起來比較直觀,注意這裡的索引是從0開始算的。

numpy.where()

返回輸入數組中滿足給定條件的元素的索引。

我們來看實例:

import numpy as np
b = np.array([[30, 40, 0], [0, 20, 10], [50, 0, 60]])
print(np.char.center('調用 where() 函數', 20, '*'))print(np.where(b > 20))print(np.transpose(np.where(b > 20)))
# 返回***調用 where() 函數****(array([0, 0, 2, 2]), array([0, 1, 0, 2]))[[0 0] [0 1] [2 0] [2 2]]

這裡面我們輸入的條件是大於20,數組中大於20的數的索引都被查找出來了。

numpy.extract()

根據某個條件從數組中抽取元素,返回滿條件的元素。

我們來看實例:

import numpy as np
x = np.arange(9.).reshape(3, 3)print(np.char.center('我們的數組是', 20, '*'))print(x)# 定義條件, 選擇偶數元素condition = np.mod(x, 2) == 0print(np.char.center('按元素的條件值', 20, '*'))print(condition)print(np.char.center('使用條件提取元素', 20, '*'))print(np.extract(condition, x))
# 返回*******我們的數組是*******[[0. 1. 2.] [3. 4. 5.] [6. 7. 8.]]******按元素的條件值*******[[ True False True] [False True False] [ True False True]]******使用條件提取元素******[0. 2. 4. 6. 8.]

例子中,我們先定義了一個條件,就是選擇偶數。然後我們可以列印這個數組每個元素是否滿足條件。最後我們調用 extract() 方法返回滿足條件的元素。注意這裡返回的是元素,而不是元素的索引。總結

本文向大家介紹了 NumPy 的排序與篩選函數,熟練掌握和運用這些函數可以很輕鬆地幫助我們達到特定的目標,而不用自己去重複造輪子。大家在後續的代碼中遇到類似的情況應該要優先想到這些函數。

參考

https://numpy.org/devdocs/reference/routines.sort.html

文中示例代碼:python-100-days

相關焦點

  • 統計師的Python日記【第3天:Numpy你好】
    本文是【統計師的Python日記】第3天的日記回顧一下,第1天學習了Python的基本頁面、操作,以及幾種主要的容器類型;第2天學習了python的函數、循環和條件、類。複習大綱:一、為什麼學Python?二、安裝與熟悉三、容器四、函數五、循環與條件六、類日記小結原文複習(點擊查看):【第1天:誰來給我講講Python?】
  • D02 Numpy常用函數,如何優雅的遍歷一個多維數組?
    當我們想要遍歷一個多維數組的時候,如果通過不停的使用循環去遍歷,這會讓我們的代碼可讀性與性能都變得很差,numpy提供了一個函數nditer,以幫助我們遍歷數組。nditer的入參是一個數組,返回值是一個可迭代對象。nditer 默認會優先遍歷行序,通過order參數可以使其優先遍歷列序。
  • Excel函數公式:關於排序的函數和公式,全在此篇
    排序,是Excel中常用的操作,除了操作技巧之外,還有部分函數和公式可以實現排序功能。一、普通排序:RANK函數。解讀:1、此函數是常用的排序函數,可以對數據實現升序、降序排序。2、但是此函數的缺點也是很明顯的,就是當排序的數據相同時,排名會「跳躍式」填充。例如:示例中有兩個第4名,之後直接跳到第6名。並未顯示出第5名。二、中國式排序:SUMPRODUCT函數。
  • 圖解NumPy:常用函數的內在機制
    的排序函數那麼強大:Python 列表與 NumPy 數組的排序函數對比在一維情況下,如果缺少 reversed 關鍵字,那麼只需簡單地對結果再執行反向,最終效果還是一樣。為了將其轉換成兩個坐標,需要使用 unravel_index 函數:使用 unravel_index 函數的示例all 和 any 函數也支持 axis 參數:使用 all 和 any 函數的示例矩陣排序axis 參數雖然對上面列出的函數很有用,但對排序毫無用處:使用 Python 列表和 NumPy 數組執行排序的比較
  • 篩選後實現自動排序,其實很簡單,使用SUBTOTAL函數輕鬆搞定
    Hello.大家好,今天跟大家分享下如何在篩選或者隱藏數據後讓表格的序號自動排序。這個也是一個粉絲提問的問題,想要實現這樣的效果我們僅僅使用 SUBTOTAL函數就可以解決,下面就讓我們來一起操作下吧一、SUBTOTAL函數及其作用SUBTOTAL函數:返回數據區域分類匯總的結果。
  • Numpy高級操作大全!!!
    arcsin,arccos,和arctan函數返回給定角度的sin,cos和tan的反三角函數。這些函數的結果可以通過numpy.degrees()函數通過將弧度制 轉換為角度制來驗證。– numpy.power() 函數將第一個輸入數組中的元素作為底數,計算它與第二個輸入數組中相應元素的冪。– numpy.mod() 函數返回輸入數組中相應元素的除法餘數。
  • Python數據分析之numpy學習(一)
    下面將從這5個方面來介紹numpu模塊的內容:1)數組的創建2)有關數組的屬性和函數3)數組元素的獲取--普通索引、切片、布爾索引和花式索引4)統計函數與線性代數運算5)隨機數的生成數組的創建numpy中使用array()函數創建數組,array
  • Numpy 使用簡介
    學習目標:1.創建Numpy 數組2.Numpy數組的簡單運算運算3.從numpy數組中提取信息4.對numpy數組中的元素進行排序5.連接(concatenate) numpy數組如果您閱讀了之前的幾篇推送,相信您已經對python語言以及電腦程式設計有了一定的了解。
  • 手把手教你學Numpy——常用API合集
    本文轉載自【微信公眾號:五角錢的程式設計師,ID:xianglin965】,經微信公眾號授權轉載,如需轉載與原文作者聯繫今天是Numpy專題的第5篇文章,我們來繼續學習Numpy當中一些常用的數學和統計函數。
  • numpy中數組操作的相關函數
    在numpy中,有一系列對數組進行操作的函數,在使用這些函數之前,必須先了解以下兩個基本概念副本視圖副本是一個數組的完整拷貝
  • 4個Python初學者必學的Numpy小技巧
    Numpy有一個子模塊numpy.ma,它支持帶掩碼的數據數組。帶掩碼的數組包含一個普通的numpy數組和一個指示無效記錄位置的掩碼。np.ma.MaskedArray(data=arr,mask=invalid_mask)有時使用負值或字符串標記數組中的無效記錄。
  • NumPy:創建和操作數值數據
    實例:素數篩選練習:簡化假定有 sum ,你會期望看到哪些其他的函數?sum 和 cumsum 有什麼區別?實例: 數據統計populations.txt中的數據描述了過去20年加拿大北部野兔和猞猁的數量(以及胡蘿蔔)。
  • 不懂NumPy 算什麼 Python 程式設計師?|CSDN 博文精選
    numpy 數組中的元素都需要具有相同的數據類型,因此在內存中的大小相同。python 數組則無此要求。numpy 數組的方法涵蓋了大量數學運算和複雜操作,許多方法在最外層的 numpy 命名空間中都有對應的映射函數。
  • Python數據分析之NumPy數值計算
    行中第3和4列的元素print("索引結果為:\n", arr[0, 3:5])# 索引第2和3行中第3~5列的元素print("索引結果為:\n", arr[1:, 2:])# 索引第2列的元素print("索引結果為: \n", arr[:, 2])# 多維數組的索引(使用整數和布爾值索引訪問數據)# 從兩個序列的對應位置取出兩個整數來組成下標
  • 【翻譯】《利用Python進行數據分析·第2版》第4章(下)NumPy基礎:數組和矢量計算
    版》第1章 準備工作【翻譯】《利用Python進行數據分析·第2版》第2章(上)Python語法基礎,IPython和Jupyter【翻譯】《利用Python進行數據分析·第2版》第2章(中)Python語法基礎,IPython和Jupyter【翻譯】《利用Python進行數據分析·第2版》第2章(下)Python語法基礎
  • 【每天15分鐘,5天學會NumPy】第4天:常用函數
    想一想,Python 和 C 語言如何表示數組中的缺值、空值和無效值呢?Python 因為數組元素不受類型限制,可以用 None 或者 False 等表示缺值、空值和無效值。對 C 語言來說,恐怕也只能在數據的值域範圍之外,選一個特定值來表示吧?比如,假定數組存儲的是學生的成績,成績一般都是正值,所以C語言可以用-1表示缺考。
  • Excel如何在進行數據篩選後並將數據進行排序?
    Excel如何在進行數據篩選的時候,篩選之後還能將數據進行排序,這個就需要在篩選之前通過函數進行排序,才能得到這樣的結果一起來看看吧。1.當前我們對數據進行排序的話,先要對表格建立超級表就出現一些按鈕。
  • Excel第三課資料排序和篩選
    Excel第三課:資料排序和篩選資料排序用處:用處很廣泛,就是將數據進行排序,方便對比分析。
  • 清晰易懂的Numpy進階教程
    如何將數據導入和導出csv文件3. 如何保存和加載numpy對象4. 如何按列或行拼接numpy數組5. 如何按列對numpy數組進行排序6. 如何用numpy處理日期7.高階numpy函數介紹8. 小結1.
  • Pandas學習之旅:排序函數sort_values()
    pandas中的sort_values()函數原理類似於SQL中的order by,可以將數據集依照某個欄位中的數據進行排序,該函數即可根據指定列數據也可根據指定行的數據排序