首頁 > 軟體

範例詳解Python中的numpy.abs和abs函數

2022-08-19 22:02:15

說在最前

不知道小夥伴們在寫程式碼的時候有沒有區分開numpy.abs和abs函數,別小看這兩個函數,如果在寫程式的時候正確區分使用這兩個函數可以使自己的程式執行效率大大提升。

別看這兩個函數都能對整數求絕對值,但他們倆的返回值型別完全不一樣,如果傻傻地混為一談,將會使你的程式執行時間被大大拖累!

今天筆者就帶小夥伴們看看,這兩個函數究竟該怎麼正確使用才能使自己的程式執行效率得到提升。

先看範例程式-abs()函數

注意觀察變數row和語句temp=row-1

import time

row=-1000
row=abs(row)  #這裡的函數是abs()

start_time = time.time()#記錄程式執行到這(記為A)的時間

for i in range(row):
    for j in range(1000):
        temp=row-1    #temp在這裡只是用來接收row-1的結果

end_time = time.time()#記錄程式執行到這(記為B)的時間
print(end_time-start_time)#輸出A和B程式碼間的程式執行時間

執行時間為:0.08079314231872559

再看範例程式-numpy.abs()函數

注意觀察變數row和語句temp=row-1

import numpy
import time

row=-1000
row=numpy.abs(row)   #這裡的函數是numpy.abs()

start_time = time.time()#記錄程式執行到這(記為A)的時間

for i in range(row):
    for j in range(1000):
        temp=row-1    #temp在這裡只是用來接收row-1的結果

end_time = time.time()#記錄程式執行到這(記為B)的時間
print(end_time-start_time)#輸出A和B程式碼間的程式執行時間

執行時間為:0.20246124267578125

觀察兩個程式的結果

觀察兩個程式的相同程式碼段執行時間的結果,你會發現作用都是用來取整的abs()函數和numpy.abs()函數,執行時間竟然差了大約2.5倍!

小夥伴們看到這裡是不是十分驚訝和不解?為什麼相同的程式碼段執行時間竟然大不相同?雖然在本文章中,它們的相同程式碼段執行時間只差了0點幾秒,但是在做資料處理時,龐大的資料處理足足可以使這微小的差距瞬間拉大,造成本來可以幾秒鐘執行結束的程式你卻用了幾分鐘跑完的尷尬局面。

分析解釋

注意觀察兩個程式的變數row,

第一個程式

row=abs(row)

第二個程式

row=numpy.abs(row)

小夥伴們第一眼看好像這兩個函數除了外貌不同外,也沒啥不同,都是對變數row取絕對值,但是這兩個函數恰恰在返回值型別上不同。abs()函數返回的型別是int型而numpy.abs()函數返回的型別卻是ndarray。小夥伴們可以使用Type()函數來看變數row的型別,或者去numpy的官網看一下numpy.abs()函數的說明,連結附上:numpy.abs()函數官方說明

int型別這裡不做過多解釋,有興趣的小夥伴可以自己去了解相關知識。

而ndarray型別,是numpy庫裡的陣列型別,它是numpy庫裡的一種類(numpy.ndarray),小夥伴們可以去官網上看看有關ndarray型別的說明。連結附上:numpy.ndarray型別官方說明

有了上面的基礎,我們再來理解為什麼會出現相同程式碼段執行時間不同就變得容易許多了。其主要原因在於

temp=row-1

這段程式碼。如果row變數是ndarray型別,那麼ndarray型別減去int型別(常數1是int型別)就會存在不同型別間的變數進行轉換的問題(這種轉換是系統自己完成的,也可以稱之為隱藏式地轉換),這會使程式有額外的開銷,使程式的執行效率降低。而如果row變數是int型別就不會出現這種問題,所以這就是使兩段相同的程式碼執行時間不同的根本原因所在。

另外numpy.abs()函數希望的引數型別是ndarray型別,而abs()函數希望的引數型別之一是int型別,所以numpy.abs(row)和abs(row)也存在上述問題。

拓展

雖然numpy.abs()函數對單個元素(整型、浮點型等等)的處理較abs()函數慢,但如果元素很多,可以把這些元素組合起來形成一個ndarray型別陣列,這時使用numpy.abs()函數(ndarray型別做實際引數)就要比用abs()函數迴圈處理快得多啦。

補充:numpy abs()報錯

我在用numpy的abs()給陣列取絕對值的時候出現了這個問題,很明顯是dtype的問題

'<U32'是unsigned 32的含義,那麼這個格式本來就沒有符號,我還非要取絕對值那肯定會報錯的呀!

回過頭去看了看果然是append進陣列的時候忘了把格式強轉成float了

OK!轉換!解決!

ufunc 'absolute' did not contain a loop with signature matching types dtype('<U32') dtype('<U32')

總結

單個元素用abs()函數

多個元素並行處理用numpy.abs()函數

使用函數和寫程式碼時一定要注意變數隱藏式地轉換,因為這能在無形之中拖慢你程式的執行速度。

到此這篇關於Python中numpy.abs和abs函數的文章就介紹到這了,更多相關Python numpy.abs和abs函數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com