Python Numpy中返回下标操作函数-节约时间的利器
如果覺得Python慢,那么首先應(yīng)該想到是不是沒有用對(duì)。
Numpy是Python中自帶的一個(gè)數(shù)值計(jì)算庫(kù),包含了大量數(shù)值計(jì)算的常用方法。其底層大量使用C/C++(超過50%的代碼量),矩陣計(jì)算調(diào)用LAPACK庫(kù)(Fortran),同時(shí)在大量代碼優(yōu)化的層面做了工作,使得其內(nèi)置方法速度奇快。
Numpy的設(shè)計(jì)也頗具人性化, 有許多具有特色又好用的方法可供使用。其中以arg開頭函數(shù)就是專門為返回下標(biāo)(集)而設(shè)計(jì)的,總共有5個(gè)這樣的函數(shù),它們簡(jiǎn)單易用,在許多問題里可以將程序極度簡(jiǎn)化,從而提高我們的工作效率。
1. argwhere()
這個(gè)函數(shù)與where基本一致,主要用于查找元素所在的位置:
a = np.array([46, 57, 23, 39, 1, 10, 0, 120])# 找出a中大于1的所有元素的下標(biāo) np.argwhere(a > 1) Out: array([[0],[1],[2],[3],[5],[7]], dtype=int64) # 找出a中所有小于10的元素的下標(biāo) np.argwhere(a < 10) Out: array([[4],[6]], dtype=int64)如果拿到一個(gè)需要返回元素下標(biāo)的任務(wù),我們從C直接考慮的話可能想到的是去遍歷元素,再利用一個(gè)臨時(shí)變量來計(jì)數(shù),在匹配過程中返回這個(gè)計(jì)數(shù)值。雖然實(shí)現(xiàn)起來也很簡(jiǎn)單,但速度不是很快。而用這種方法,簡(jiǎn)單易懂,同時(shí)又超快。
2. argmin(),argmax()
最大,最小值的下標(biāo)。這種操作應(yīng)該也是我們非常常用的,而這兩個(gè)函數(shù)的用法實(shí)際上和np.max(),np.min()的用法是完全一樣的。
a = np.array([46, 57, 23, 39, 1, 10, 0, 120]) np.argmin(a) Out: 6 np.argmax(a) Out: 73. argsort()
這個(gè)函數(shù)非常厲害,它首先將輸入的數(shù)組進(jìn)行升序排列,再將排列后各元素的原下標(biāo)依次返回。這種操作在一些需要聯(lián)動(dòng)排序的時(shí)候特別管用。比如我們之前講過的在PCA的計(jì)算過程中,需要對(duì)特征值從大到小排序,同時(shí)要對(duì)它們對(duì)應(yīng)的特征向量也排序。那么這個(gè)時(shí)候直接返回特征值排序后的原下標(biāo)就能極大程序上簡(jiǎn)化我們的代碼,同時(shí)又能節(jié)約大量的時(shí)間。
a = np.array([46, 57, 23, 39, 1, 10, 0, 120])np.argsort(a) Out: array([6, 4, 5, 2, 3, 0, 1, 7], dtype=int64)a[np.argsort(a)] Out: array([ 0, 1, 10, 23, 39, 46, 57, 120])上面最后一步主要是為了用它檢驗(yàn)函數(shù)的正確性,同時(shí)也方便對(duì)照分析。
根據(jù)第4行的結(jié)果,我們來看前2個(gè)元素。它返回值表示:排序后的數(shù)組中第一個(gè)元素應(yīng)該是原數(shù)組中的第7個(gè)元素0,第二個(gè)元素應(yīng)該是原數(shù)組中的第5個(gè)元素1。那么看看第7行,完全正確。
當(dāng)然,還有一個(gè)問題是np.sort本身只進(jìn)行升序排列,那么當(dāng)我們需要降序時(shí)直接將下標(biāo)進(jìn)行反序即可:
np.argsort(a)[::-1] Out: array([7, 1, 0, 3, 2, 5, 4, 6], dtype=int64)a[np.argsort(a)[::-1]] Out: array([120, 57, 46, 39, 23, 10, 1, 0])4. argpartition()
這也是一個(gè)非常神奇的函數(shù),它主要是對(duì)應(yīng)partition函數(shù)。如果只看文檔說明很有可能理解錯(cuò)誤。所以我們先簡(jiǎn)單說明一下函數(shù)的主要參數(shù)的含義。
np.argpartition(a,k)這里a是 我們的原數(shù)組,k比如好理解的一種方式是:若將a進(jìn)行排序,那么排序后的數(shù)組中的下標(biāo)為k個(gè)元素應(yīng)該處在其最終的位置。這句話有一點(diǎn)不太好理解。當(dāng)然如果我們學(xué)過歸并排序(快排的基礎(chǔ))的話,就可以理解這種分組的思路。
這個(gè)算法最終返回的下標(biāo)里面,下標(biāo)為k的元素一定處在原數(shù)組升序排列后的最終位置,它前面所有值全部小于等于它,后面所有值全部大于等于它,但其前后所有元素內(nèi)的順序是不關(guān)心的。所以這樣就自然而然地能想到,由于它只考慮該元素的最終位置,那么時(shí)間復(fù)雜度可以在很大程度上降低。
先看一個(gè)簡(jiǎn)單的例子:
a = np.array([46, 57, 23, 39, 1, 10, 0, 120])np.argpartition(a,3) Out: array([6, 4, 5, 2, 3, 0, 1, 7], dtype=int64)a[np.argpartition(a,3)] Out: array([ 0, 1, 10, 23, 39, 46, 57, 120])這里可以清楚地看到,排序后的元素中下標(biāo)為3的元素23的前面已經(jīng)全部小于它,后面已經(jīng)全部大于它,因此這個(gè)元素已經(jīng)處在其排序后的最終位置了。
那么利用這個(gè)功能,我們主要是可以用它來找出元素中第k小的元素或者是第k大的元素所在的下標(biāo)。
a[np.argpartition(a,3)[3]] Out: 23 # 第四小的元素剛好是23a[np.argpartition(a,-3)[-3]] Out[]: 46 # 這里是倒數(shù)第3小的元素,也就是第3大的元素,正是46另外,上述方法也可以指定具體的排序方法。比如上面提到的這種思想的基本排序方法是歸并排序,其實(shí)也可以指定快速排序等方法。不過在數(shù)據(jù)量級(jí)不是特別大的情況下差異并不大。
總結(jié)
以上是生活随笔為你收集整理的Python Numpy中返回下标操作函数-节约时间的利器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCA计算流程详解与实现(Python详
- 下一篇: Markdown转LaTeX的Pytho