7. 花哨的索引

  • 使用数组作为索引叫花哨的索引(Fnacy Indexing)
  • 花哨的索引让我们快速访问复杂数组的子数据集
  • 使用花哨的索引同样可以对子数据集进行写操作
  • 利用花哨的索引获得的结果与索引的形状(Shape)一致,跟被索引的数组的形状无关。
import numpy as np

# 产生10个随机数字
x = np.random.randint(100, size=10)
print("x = ", x)

indx = [2,3,7]

#用数组作为索引就是花哨的索引
a = x[indx]
print("a = ",a)

# 结果的shape跟索引的shape一致
print("a.shape = ", a.shape)
x =  [61  7 32 55 80 87 12 27 56 12]
a =  [32 55 27]
a.shape =  (3,)
indx = np.array([2,3,5,7]).reshape((2,2))
print("indx.shape = ", indx.shape)

print()
# 使用一个2x2的数组作为索引
b = x[indx]
print("b = ", b)

print()
# 结果的shape跟索引的shape一致
print("b.shape = ", b.shape)
indx.shape =  (2, 2)

b =  [[32 55]
 [87 27]]

b.shape =  (2, 2)

对于花哨的索引,可以使用两个数组分别表示,但是在索引的配对的时候,需要遵守广播规则才能一对一配对,例如下面例子:

# 花哨的索引还可以更花哨

x = np.arange(16).reshape((4,4))
print("x = ", x)
print()

print("x.shape = ", x.shape)

print()

# 我们会获得的结果是三个数字组成的数组
# 三个数字分别是(0,3), (2,1), (3,1)
r = np.array([0,2,3])
c = np.array([3,1,1])

a = x[r, c]
print("a = ", a)
print("a.shape = ",a.shape)
x =  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

x.shape =  (4, 4)

a =  [ 3  9 13]
a.shape =  (3,)

花哨的索引还可以有更花哨的用法,比如:

import numpy as np
x = np.arange(20).reshape((4,5))
print("x = ", x)
print("x.shape = ", x.shape)

print()

x =  [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
x.shape =  (4, 5)
# 1.  简单的索引和花哨的索引组合使用你

a = x[2, [3,2,1]]
print("x[2, [3,2,1]] = ", a)
print("a.shape = ", a.shape)
x[2, [3,2,1]] =  [13 12 11]
a.shape =  (3,)
# 2, 花哨的索引+切片配合服用
print()
b = x[2:, [3,2,1]]
print("x[2:, [3,2,1]] = ", b)
print("b.shape = ", b.shape)
x[2:, [3,2,1]] =  [[13 12 11]
 [18 17 16]]
b.shape =  (2, 3)
# 3. 花哨的索引+掩码

print(x)
mask = np.array([1,0,1,1,0], dtype=bool)


print(c)
c = x[[0,2,3], mask] 

print("x[[0,2,3], mask] = \n", c)
print("c.shape = ", c.shape)

print("***************")
c = x[np.array([0,2,3]).reshape(3,1), mask] 

print("x[[0,2,3], mask] = \n", c)
print("c.shape = ", c.shape)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
[ 0 12 18]
x[[0,2,3], mask] = 
 [ 0 12 18]
c.shape =  (3,)
***************
x[[0,2,3], mask] = 
 [[ 0  2  3]
 [10 12 13]
 [15 17 18]]
c.shape =  (3, 3)
# 利用花哨的索引批量修改数据

x = np.arange(10)
x[[2,4,6,8]] = 999

print(x)
[  0   1 999   3 999   5 999   7 999   9]