数组索引是指在numpy
数组中引用特定元素的方法。numpy
的数组索引又称为fancy indexing
,比其他编程语言的索引强大很多。
1. 选取数据
numpy的索引除了像其他语言一样选择一个元素,还可以间隔着选取多个元素,也可以用任意的顺序选取元素。
比如一维数组:
arr = np.random.randint(0, 10, 5)
print(arr)
#运行结果
[7 2 6 2 1]
indexes = [0, 2, 3]
print(arr[indexes])
#运行结果
[7 6 2]
indexes = [4, 0, 2]
print(arr[indexes])
#运行结果
[1 7 6]
从上面的示例看出,通过传入 indexes
数组,可以一次选择多个元素。indexes
数组中的值代表数组arr
的下标,从0
开始。
对于二维数组:
arr = np.random.randint(0, 10, (5,5))
print(arr)
#运行结果
[[5 7 3 3 2]
[2 5 6 3 6]
[4 1 1 0 1]
[6 5 8 9 1]
[2 6 5 2 0]]
rows = np.array([3, 1, 4])
cols = np.array([3, 0, 1])
print(arr[rows, cols])
#运行结果
[9 2 6]
这里 rows
和 cols
分别代表行和列的索引,从0
开始。
运行结果选取的是单个元素,分别是:arr[3, 3]
,arr[1, 0]
,arr[4, 1]
。
如果要从二维数组中通过选取行列,而不是选取单个元素的话:
arr = np.random.randint(0, 10, (5,5))
print(arr)
#运行结果
[[4 2 6 6 4]
[1 8 8 1 9]
[5 9 2 1 3]
[8 9 1 6 9]
[5 4 3 5 6]]
rows = np.array([3, 1, 4])
cols = np.array([3, 0, 1])
arr[rows[:, np.newaxis], cols]
#运行结果
[[6 8 9]
[1 1 8]
[5 5 4]]
arr[rows[:, np.newaxis], cols]
是先选取3,1,4
行,得到:
[[8 9 1 6 9]
[1 8 8 1 9]
[5 4 3 5 6]]
然后选取3,0,1
列,得到:
[[6 8 9]
[1 1 8]
[5 5 4]]
2. 与切片结合
fancy indexing
可以和之前数组的切片操作相结合:
arr = np.random.randint(0, 10, (5,5))
print(arr)
#运行结果
[[4 2 6 6 4]
[1 8 8 1 9]
[5 9 2 1 3]
[8 9 1 6 9]
[5 4 3 5 6]]
rows = np.array([3, 1, 4])
cols = np.array([3, 0, 1])
#切片在行上
print(arr[:2, cols])
#运行结果
[[6 4 2]
[1 1 8]]
#切片在列上
print(arr[rows, 1:])
#运行结果
[[9 1 6 9]
[8 8 1 9]
[4 3 5 6]]
arr[:2, cols]
先选择前2
行,然后按照 cols
顺序选择列。arr[rows, 1:]
按照 rows
顺序选择行,然后选择后4
列。
3. 与掩码结合
fancy indexing
也可以和之前介绍的掩码相结合来过滤数组:
arr = np.random.randint(0, 10, (5,5))
print(arr)
#运行结果
[[4 2 6 6 4]
[1 8 8 1 9]
[5 9 2 1 3]
[8 9 1 6 9]
[5 4 3 5 6]]
rows = np.array([3, 1, 4])
mask = np.array([True, False, False, False, True])
print(arr[rows[:, np.newaxis], mask])
#运行结果
[[8 9]
[1 9]
[5 6]]
arr[rows[:, np.newaxis], mask] 先按照 rows 的顺序选择行,然后用mask过滤掉 False 的列。
最后剩下的是 3,1,4
行的 第一列和**最后一列**
。
4. 修改数据
最后,fancy indexing
还有个重要的作用是修改数据,我们通过fancy indexing
选取数据之后,可以直接修改它们。
arr = np.random.randint(0, 10, (5,5))
print(arr)
#运行结果
[[6 4 7 8 1]
[0 3 5 0 6]
[8 9 4 7 0]
[3 0 0 9 1]
[4 5 5 0 5]]
rows = np.array([3, 1, 4])
cols = np.array([3, 0, 1])
arr[rows, cols] = [100] * len(arr[rows, cols])
print(arr)
#运行结果
[[ 6 4 7 8 1]
[100 3 5 0 6]
[ 8 9 4 7 0]
[ 3 0 0 100 1]
[ 4 100 5 0 5]]
上面的示例中,将fancy indexing
选取出的值修改为100。
注意,[100] * len(arr[rows, cols])
这个代码是根据fancy indexing
选取出的元素个数来决定将几个值修改成100
。
5. 总结回顾
numpy
数组索引的意义在于它可以使数组中的数据更加灵活和易于管理。
通过使用索引,开发人员可以快速访问数组中的特定元素,而不需要遍历整个数组。
这可以大大加快计算速度和减少内存使用。
此外,数组索引还可以用于数组的重构和维护。
通过对数组索引的有效使用,开发人员可以轻松地修改和维护数组中的数据,而不会影响到其他使用该数组的程序。