HOWTO · NumPy
在 NumPy 数组中查找元素的第一个索引
本教程演示了如何在 python 中查找数组中元素的索引
本页内容
若要查找一维 NumPy 数组中某个值首次出现的位置,并且确定该值存在,可以使用 np.where(array == value)[0][0]。该表达式会返回第一个匹配位置;如果该值可能不存在,请先检查是否存在匹配项。NumPy 索引从零开始。
使用 np.where() 查找第一个匹配索引
np.where(condition) 会返回一个元组,其中每个数组维度各对应一个索引数组。对于一维数组,元组的第一个元素就是所有匹配位置组成的数组。取出其中第一个元素即可得到首次匹配的位置。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
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() 一样,它会返回一个索引数组元组,每个数组维度对应一个索引数组。对于一维数组,取出元组中的第一个数组即可。
本节中的代码以及显示的标签或输出仍为英文。
import numpy as np
values = np.array([4, 7, 4, 9])
positions = np.nonzero(values == 4)[0]
print(positions.tolist())
结果会按数组中的顺序包含所有匹配位置。只有在确认数组非空后,才能用 positions[0] 取得第一个匹配位置。对于多维数组,元组中的每个元素都包含沿一个维度的坐标;将对应位置的坐标配对,即可定位每个匹配项。
使用 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()会返回 0,但这个位置不代表存在匹配项。如果掩码为空,np.argmax()则会引发ValueError。上面的防护表达式会先检查np.any(mask),因此无论掩码中没有 True 值还是掩码为空,都会返回None。
对于常见的数值数组查找,需要第一个或全部匹配项时,np.where() 都是直接的选择。若要获取相同的 True 条件位置,可以使用 np.nonzero();对布尔掩码使用 np.argmax() 前应先检查;已经适合使用 Python 列表时可选 list.index();需要自定义匹配规则时则可使用循环。