HOWTO · NumPy
在 NumPy 陣列中查詢元素的第一個索引
本教程演示瞭如何在 python 中查詢陣列中元素的索引
本頁內容
若要在一維 NumPy 陣列中尋找某個值的第一個索引,且確定一定有符合項目,可以使用 np.where(array == value)[0][0]。這個運算式會回傳第一個符合的位置;若該值可能不存在,請先檢查是否有符合項目。NumPy 索引從零開始。
使用 np.where() 尋找第一個符合的索引
np.where(condition) 會回傳一個 tuple,其中包含各維度的索引陣列。對一維陣列而言,tuple 的第一個項目就是所有符合位置的清單。選取其中第一個位置即可取得第一筆符合項目。
執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import numpy as np
values = np.array([10, 20, 30, 40, 50, 20])
target = 20
matches = np.where(values == target)[0]
print(int(matches[0]))
1
在此,matches 包含 20 出現的兩個位置,而 matches[0] 會選取第一個位置。若沒有任何值符合條件,matches 就不會有元素,因此進行索引時會引發 IndexError。如果不確定是否有符合項目,請先檢查 matches.size 再選取索引。三個引數的形式 np.where(condition, x, y) 則會依條件從 x 或 y 選取值;這與此處用來回傳索引的形式不同。
使用 np.nonzero() 尋找符合的索引
對布林條件使用 np.nonzero() 時,它會回傳值為 True 的項目索引。和單一引數形式的 np.where() 一樣,它會回傳由索引陣列組成的 tuple,每個陣列維度各有一個索引陣列。若陣列是一維,取用 tuple 中的第一個陣列即可。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import numpy as np
values = np.array([4, 7, 4, 9])
positions = np.nonzero(values == 4)[0]
print(positions.tolist())
結果會依陣列中的順序包含所有符合的位置。只有在確認陣列非空後,才能使用 positions[0] 取得第一個符合項目。對多維陣列而言,tuple 中的每個項目都包含某一維度的座標;將對應位置配對,即可定位每個符合項目。
使用 np.argmax() 尋找布林符合項目
np.argmax() 會回傳最大值的位置。套用在布林遮罩上時,它會回傳第一個 True 的位置,因為 True 大於 False。全為 False 的遮罩也會得到 0,因此使用結果前請先確認確實有符合項目。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import numpy as np
values = np.array([5, 8, 3, 8])
mask = values == 8
first = int(np.argmax(mask)) if np.any(mask) else None
print(first)
這種寫法在目標不存在時會得到 None,否則會回傳第一個符合的位置。若要取得所有符合位置,請改用 np.where() 或 np.nonzero()。
將陣列轉換後使用 list.index()
將一維陣列轉換成 Python 清單後,就能使用清單方法 list.index()。它會回傳值第一次出現的位置。轉換會建立一個 Python 清單,因此會增加時間與記憶體成本;對小型陣列或原本就在使用清單的程式而言,這種方式通常最方便。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import numpy as np
values = np.array([10, 20, 30, 20])
items = values.tolist()
target = 20
index = items.index(target) if target in items else None
print(index)
先檢查是否包含該值,就能明確地在找不到時回傳 None;若值不存在卻直接呼叫 items.index(target),則會引發 ValueError。檢查與查找都會各自掃描清單,因此若只查找一次,也可以在呼叫 list.index() 時捕捉 ValueError。
使用迴圈處理自訂邏輯
當每個元素都需要套用不容易用 NumPy 向量化條件表達的自訂檢查時,迴圈就很實用。先將結果初始化為代表找不到的值,再於找到第一個符合項目時立即停止。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import numpy as np
values = np.array([12, 15, 18, 21])
index = None
for position, value in enumerate(values):
if value % 2 == 0 and value > 12:
index = position
break
print(index)
迴圈會逐一檢查元素,並在第一個同時符合兩項條件的值出現時結束。若只是檢查是否相等,使用 NumPy 遮罩通常更精簡;當比對規則需要自訂分支或狀態時,則可使用迴圈。
處理找不到符合項目、重複值與陣列維度
請依照任務選擇適合的結果形式:
- 若要找一維陣列中的第一個符合項目,使用
np.where()或np.nonzero()取得位置,確認至少有一個位置,再選取第一個。 - 若要取得所有符合項目,請保留完整索引陣列。重複值會對應到多個位置;需要全部結果時,不要只選取
[0]。 - 對二維陣列而言,
np.where(matrix == target)會回傳(row_indices, column_indices)。對應項目會組成座標配對。例如,(rows[0], columns[0])是第一個符合項目的列與欄座標,不是單一的扁平索引。 - 若確實需要多維陣列中的扁平位置,請先將陣列攤平,再搜尋攤平後的值。必要時可使用
np.unravel_index()將扁平位置轉回座標。 - 對非空且全為 False 的遮罩,
np.argmax()會回傳零,但該位置不代表有符合項目。若遮罩是空的,np.argmax()則會引發ValueError。上方的防護運算式會先檢查np.any(mask),因此無論遮罩是沒有任何 True 值,或是空遮罩,都會回傳None。
對一般數值陣列查找而言,需要第一個或所有符合項目時,np.where() 是直接的選擇。若要取得條件為 True 的相同位置,也可使用 np.nonzero();對布林遮罩使用 np.argmax() 時,請先確認有符合項目;若程式已在使用 Python 清單,可採用 list.index();需要自訂比對規則時,則可使用迴圈。