HOWTO · NumPy
如何在 NumPy 中對映函式
使用 numpy.vectorize() 或 map() 搭配 lambda,將 Python 函式套用到 NumPy 陣列的每個值。了解每種方法的工作原理以及使用時機。
本頁內容
若要將純量 Python 函式套用至 NumPy 陣列中的每個值,可以用 numpy.vectorize() 包裝該函式,或使用 Python 的 map() 搭配 lambda,再將結果轉換為陣列。當你想重用純量邏輯時,這兩種方式都很實用;但它們不能與 NumPy 原生的陣列運算混為一談。若 NumPy 已提供等效運算,通常直接使用該運算更合適。
使用 numpy.vectorize() 將函式逐一套用至元素
numpy.vectorize() 能調整一次只接受單一值的函式,讓你可以用陣列呼叫它。它會逐一處理陣列中的元素,並回傳由運算結果組成的陣列。若既有的 Python 邏輯是為純量值撰寫,而你想將它用於陣列資料,這種方式會很方便。
以下範例會包裝一個將輸入值平方的純量函式,再將它套用至五個整數:
import numpy as np
def square(value):
return value ** 2
values = np.array([1, 2, 3, 4, 5])
square_each = np.vectorize(square)
result = square_each(values)
print(result)
在此,square 仍是一般的 Python 函式;np.vectorize() 提供以陣列呼叫函式的介面。它只是便利包裝器,並非效能最佳化:不會將函式轉換為已編譯的 NumPy 運算。若是 NumPy 已支援的算術運算,例如 values ** 2,直接使用這類運算式會更簡潔,也會直接使用 NumPy 的陣列運算。當包裝純量邏輯能讓程式碼更清楚或更容易重用時,再使用 numpy.vectorize()。
使用 map() 搭配 lambda 函式
Python 內建的 map() 會對可疊代物件中的每個項目呼叫一次函式。lambda 可以簡潔地在行內定義小型函式。輸入若是 NumPy 陣列,map() 會產生包含映射結果的迭代器;用 list() 包裝該迭代器,再將產生的清單傳給 np.array(),即可建立陣列。
以下範例使用 lambda 將相同的值平方,再把映射結果轉換為 NumPy 陣列:
import numpy as np
values = np.array([1, 2, 3, 4, 5])
mapped_values = map(lambda value: value ** 2, values)
result = np.array(list(mapped_values))
print(result)
lambda 會分別接收陣列中的每個值,而 map() 會依序產生各值的平方結果。將迭代器轉換為清單時會逐一取出其中的值;接著 np.array() 會根據這些值建立陣列。若只是短小的純量運算,而且適合直接寫在映射呼叫旁邊,這種方式就很實用。若邏輯較長,則可改為定義具名函式,讓程式碼更容易閱讀與維護,並將該函式傳給 map() 取代 lambda。
若想為既有的純量函式提供陣列形式的呼叫介面,可選擇 numpy.vectorize()。若要進行簡短的行內轉換,尤其是轉換前會用到產生的迭代器,則可選擇搭配 lambda 的 map()。像是將所有值平方這類運算,若 values ** 2 能表達預期的計算方式,請優先使用 NumPy 的直接運算式。這些方法代表套用 Python 邏輯的不同方式,並不能據此認定其中一種映射方式比另一種更快。