切片和索引

ndarray 数组可以基于 0~n的下标进行索引,切片对象可以通过内置的 slice()函数,并设置 start、stop及 step 参数,从原数组中分割出一个新数组

# 创建 ndarray 对象
ar_np = np.arange(10)
# 索引从 2 开始到索引 7 结束,间隔为 2
s = slice(2,7,2)
print(ar_np[s])  # 输出结果: [2 4 6]

通过冒号分隔切片参数 start:stop:step 进行切片操作

# 创建 ndarray 对象
ar_np = np.arange(10)
print('数组 ar_np 为:{}'.format(ar_np))  # 输出结果:数组 ar_np 为:[0 1 2 3 4 5 6 7 8 9]

s_rs = ar_np[2]
print('数组 ar_np索引2: {}'.format(s_rs))  # 输出结果:数组 ar_np索引2: 2

# 从索引 2 开始,到索引 7 结束
s_rs = ar_np[2:7]
print('数组 ar_np 从索引 2 开始,到索引 7 结束:\n{}'.format(s_rs))

# 输出结果:
# 数组 ar_np 从索引 2 开始,到索引 7 结束:
# [2 3 4 5 6]

# 从索引 2 开始,到索引 7 结束,间隔为 2
s_rs = ar_np[2:7:2]
print('数组 ar_np 从索引 2 开始,到索引 7 结束,间隔为 2:\n{}'.format(s_rs))

# 输出结果:
# 数组 ar_np 从索引 2 开始,到索引 7 结束,间隔为 2:
# [2 4 6]

对于多维数组,上述索引提取方法同样适用:

ar_np = np.array([[1, 2, 3],[4, 5, 6],[4, 8, 9]])
print('初识数组:\n{}'.format(ar_np))

# 输出结果:
# 初识数组:
#   [[1 2 3]
#    [4 5 6]
#    [4 8 9]]

# 从某个索引处开始分割
print('从数组索引 ar_np[1:]处开始分割:\n{}'.format(ar_np[1:]))

# 输出结果:
# 从数组索引 ar_np[1:]处开始分割:
#   [[4 5 6]
#     [4 8 9]]

print('从数组索引 ar_np[1:]处开始分割,到 ar_np[2]处结束:\n{}'.format(ar_np[1:2]))

# 输出结果:
# 从数组索引 ar_np[1:]处开始分割,到 ar_np[2]处结束:
#   [[4 5 6]]

print('从数组索引 ar_np[1:]处开始分割,到 ar_np[2]处结束,步长为 2:\n{}'.format(ar_np[0:3:2]))

# 输出结果:
# 从数组索引 ar_np[1:]处开始分割,到 ar_np[2]处结束,步长为 2:
#   [[1 2 3]
#    [4 8 9]]

切片还包括省略号(...), 使选择元祖的长度与数组的维度相同.

print('第 2 列元素:{}'.format(ar_np[...,1]))

# 输出结果:
#  第 2 列元素:[2 5 8]

print('第 2 行元素:{}'.format(ar_np[1,...]))

# 输出结果:
#  第 2 行元素:[4 5 6]

print('第 2 列及剩下的所有元素:\n{}'.format(ar_np[...,1:]))

# 输出结果:
# 第 2 列及剩下的所有元素:
# [[2 3]
#  [5 6]
#  [8 9]]

整数数组索引

np_ar = np.array([[1, 2],[3, 4],[5, 6]])
# 获取坐标轴为(0,0)、(1,1)和(2,0)的元素
point_ar = np_ar[[0, 1, 2],[0, 1, 0]]
print(point_ar)  # 输出结果: [1 4 5]
np_ar = np.array([[0, 1, 2],[3, 4, 5],[6, 7, 8],[9, 10, 11]])
print('初识数组:\n{}'.format(np_ar))

# 输出结果:
# 初识数组:
#  [[ 0  1  2]
#   [ 3  4  5]
#   [ 6  7  8]
#   [ 9 10 11]]

rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]])
target_ar = np_ar[rows, cols]
print('初识数组 np_ar四个角的元素是:\n{}'.format(target_ar))

# 输出结果:
# 初识数组 np_ar四个角的元素是:
#  [[ 0  2]
#   [ 9 11]]

布尔索引

通过一个布尔数值索引目标数组;

布尔索引可以通过布尔运算获取符合指定条件的元素的数组

np_ar = np.array([[1, 2, 3],[4, 5, 6],[4, 8, 9]])
print('初识数组:\n{}'.format(np_ar))

# 输出结果:
# 初识数组:
#  [[1 2 3]
#   [4 5 6]
#   [4 8 9]]

# 获取初识数组中大于 5 的元素
bg_5 = np_ar[np_ar > 5]
print('初识数组中大于 5 的元素是:\n{}'.format(bg_5))

# 输出结果:
#  初识数组中大于 5 的元素是:
#   [6 8 9]

使用取补运算符(~)过滤 NaN

np_ar = np.array([np.nan, 1, 2, 5, np.nan, 8])
print('初识数组:{}'.format(np_ar))  # 输出结果: 初识数组:[nan  1.  2.  5. nan  8.]

filter_nr = np_ar[~np.isnan(np_ar)]
print('过滤 NaN 后的数组:{}'.format(filter_nr))  # 输出结果: 过滤 NaN 后的数组:[1. 2. 5. 8.]

从数组中过滤掉非复数元素

np_ar = np.array([1, 2+6j, 5, 3.5, 3.5+5j])
filter_nr = np_ar[np.iscomplex(np_ar)]
print('过滤非复数后的数组:{}'.format(filter_nr))

# 输出结果:
过滤非复数后的数组:[2. +6.j 3.5+5.j]

花式索引

利用整数数组进行索引;

花式索引将索引数组的值作为目标数组的某个轴的下标取值;

对使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;

如果目标数是二维数组,那么索引的结果就是对应下标的行

传入顺序索引数组:

np_ar = np.arange(32).reshape((8,4))
print('初始数组:\n{}'.format(np_ar))

# 输出结果:
# 初始数组:
#  [[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]
#   [12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]
#   [24 25 26 27]
#   [28 29 30 31]]

fancy_ar = np_ar[[4, 2, 1, 7]]
print('花式结果:\n{}'.format(fancy_ar))

# 输出结果:
# 花式结果:
#  [[16 17 18 19]
#   [ 8  9 10 11]
#   [ 4  5  6  7]
#   [28 29 30 31]]

传入倒序索引数组:

np_ar = np.arange(32).reshape((8,4))
fancy_ar = np_ar[[-4, -2, -1, -7]]
print('花式结果: \n{}'.format(fancy_ar))

# 输出结果
# 花式结果: 
#  [[16 17 18 19]
#   [24 25 26 27]
#   [28 29 30 31]
#   [ 4  5  6  7]]

传入多个索引数组(使用 np.ix_)

np_ar = np.arange(32).reshape((8,4))
fancy_ar = np_ar[np.ix_([1, 5, 7, 2],[0, 3, 1, 2])]
print('花式结果: \n{}'.format(fancy_ar))

# 输出结果:
# 花式结果: 
#  [[ 4  7  5  6]
#   [20 23 21 22]
#   [28 31 29 30]
#   [ 8 11  9 10]]