淘先锋技术网

首页 1 2 3 4 5 6 7

numpy 的索引与切片

整数索引

import numpy as np

x = np.arange(10)
print(x)
# [0 1 2 3 4 5 6 7 8 9]

x[3]
# 3

切片索引

numpy 的切片索引使用方法和python list 中的切片索引相同

x[a : b : c = 1] 就是访问 x 的从索引为 a 到索引为 b-1 的元素,c表示步长,步长默认为 1

步长,相当于我们走路的步伐,步长为1就是依次访问每一个元素,步长为2就是按照 1,3,5 … 的顺序来访问

对一维数组的切片

x[:6] 相当于 x[0:6]

x[6:] 相当于 从索引6到最后一个元素(包括最后一个元素)

x = np.arange(1,9)
print(x)

# [1 2 3 4 5 6 7 8]

# 前六个元素,不包括索引为6的元素
print(x[0:6])
# [1 2 3 4 5 6]

# 相当于 x[0:6]
print(x[:6])
# [1 2 3 4 5 6]

print(x[:6:2])
# [1 3 5]

print(x[2:])
# [3 4 5 6 7 8]

print(x[2::2])
# [3 5 7]

print(x[2:-1])
# [3 4 5 6 7]

print(x[:])
# [1 2 3 4 5 6 7 8]

print(x[::-1])
# [8 7 6 5 4 3 2 1]

对二维数组的切片

二维数组有两个切片,两个切片以逗号分割,第一个切片是行的切片,第二个切片是列的切片

行的切片索引

x = np.arange(11,36).reshape(5,-1)
print(x)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]


# 二维数组的前两行
print(x[0:3])

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]]

# 二维数组的第二行和第四行
print(x[1:5:2])

#[[16 17 18 19 20]
# [26 27 28 29 30]]

# 二维数组从第二行到最后一行
print(x[2:])

# [[21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

# 二维数组前两行
print(x[:2])

# [[11 12 13 14 15]
# [16 17 18 19 20]]

# 二维数组的后两行
print(x[-2:])

# [[26 27 28 29 30]
# [31 32 33 34 35]]

# 二维数组第一行到倒数第三行
print(x[:-2])

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]]

# 二维数组本身
print(x[:])

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

列的切片索引

# 第三行所有列的元素
print(x[2,:])

# [21 22 23 24 25]

# 所有行的第三列,虽然是一列的元素,但会以一维数组的形式返回
y = x[:,2]
print(y)
print(type(y))
print(y.shape)

# [13 18 23 28 33]
# <class 'numpy.ndarray'>
# (5,)

# 二维数组的所有行,所有列的元素,也就是二维数组自身
print(x[:,:])

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

print(x)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

# 二维数组奇数行,奇数列的元素
print(x[::2,::2])

# [[11 13 15]
# [21 23 25]
# [31 33 35]]

# 倒着访问每一行
print(x[::-1,:])

# [[31 32 33 34 35]
# [26 27 28 29 30]
# [21 22 23 24 25]
# [16 17 18 19 20]
# [11 12 13 14 15]]

# 倒着访问每一行每一列的元素
print(x[::-1,::-1])

# [[35 34 33 32 31]
# [30 29 28 27 26]
# [25 24 23 22 21]
# [20 19 18 17 16]
# [15 14 13 12 11]]

# 倒着访问每一列的元素
print(x[:,::-1])

# [[15 14 13 12 11]
# [20 19 18 17 16]
# [25 24 23 22 21]
# [30 29 28 27 26]
# [35 34 33 32 31]]

使用二维数组的切片修改元素

x = np.arange(11,36).reshape(5,-1)
print(x)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

# 奇数行,2,5列的元素全部修改为0
x[::2,1::3] = 0
print(x)

# [[11  0 13 14  0]
# [16 17 18 19 20]
# [21  0 23 24  0]
# [26 27 28 29 30]
# [31  0 33 34  0]]

整数数组索引

nmupy的 array 与python 的 list 的切片的区别除了numpy的切片会返回数据的视图之外,

还有一个区别:numpy的切片可以是一个数组

x = np.arange(1,9)

index = [0,1,2]
print(x[index])

# [1 2 3]

index = [0,1,-1]
print(x[index])

# [1 2 8]

X = np.arange(11,36).reshape(5,-1)
print(X)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

# 二维数组的 0,1,2 行
index = [0,1,2]
print(X[index])

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]]

# 二维数组的 第1行,第2行和最后一行
index = [0,1,-1]
print(X[index])

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [31 32 33 34 35]]

# 相当于 X[0,2],X[1,3],X[2,4]
row = [0,1,2]
col = [2,3,4]
print(X[row,col])

# [13 19 25]

可以使用切片访问一维数组,使其返回一个二维数组,并且不会改变原数据

x = np.arange(1,9)
r = np.array([[0,1],[3,4]])

print(x[r])

# [[1 2]
# [4 5]]
    
print(x)
# [1 2 3 4 5 6 7 8]

X = np.arange(11,36).reshape(5,-1)
print(X)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

r = np.array([[0,1],[3,4]])
print(X[r])

# [[[11 12 13 14 15]
#  [16 17 18 19 20]]
#
# [[26 27 28 29 30]
#  [31 32 33 34 35]]]

print(X)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

打印二维数组的四个角

X = np.arange(11,36).reshape(5,-1)

r = np.array([[0,0],[4,4]])
c = np.array([[0,4],[0,4]])
y = X[r,c]

print(y)

# [[11 15]
# [31 35]]

可以借助切片与整数数组组合

X = np.arange(11,36).reshape(5,-1)
print(X)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]
 
y = X[0:3,[1,2,3]]
print(y)

# [[12 13 14]
# [17 18 19]
# [22 23 24]]

布尔索引

numpy 中索引可以是一个 布尔类型的数组

x = np.arange(1,9)

# 表示将 x 的所有元素依次与 5 比较,返回一个布尔类型的数组
y = x>5
print(y)

# [False False False False False  True  True  True]

print(type(y))
# <class 'numpy.ndarray'>

# 访问索引位置为True的元素
print(x[y])
# [6 7 8]
x = np.array([np.nan,1,2,np.nan,3,4,5])
print(f"x:{x}")

y = np.logical_not(np.isnan(x))
print(f"y:{y}")

print(f"x[y]:{x[y]}")

# x:[nan  1.  2. nan  3.  4.  5.]
# y:[False  True  True False  True  True  True]
# x[y]:[1. 2. 3. 4. 5.]

X = np.arange(11,36).reshape(5,-1)
print(X)

y = X>25
print(y)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]

# [[False False False False False]
# [False False False False False]
# [False False False False False]
# [ True  True  True  True  True]
# [ True  True  True  True  True]]

print(X[y])
# [26 27 28 29 30 31 32 33 34 35]

ndarray的副本与视图

python的 list 的切片返回是原数据的副本,即开辟了一个新的内存地址,

numpy 以效率为主,所以 numpy 的切片返回的是原数据的视图,即不会创建新的内存地址,而是对原数据内存地址的引用

numpy 中所有的运算操作符都不会为数组创建副本

import numpy as np

x = np.arange(1,10).reshape(3,-1)
print(x)

# [[1 2 3]
# [4 5 6]
# [7 8 9]]

y = x
print(y)

# [[1 2 3]
#  [4 5 6]
#  [7 8 9]]

y[1,1] = 999
print(y)

# [[  1   2   3]
# [  4 999   6]
# [  7   8   9]]

print(x)

# [[  1   2   3]
# [  4 999   6]
# [  7   8   9]]

np.ndarray.copy() 可以创建一个副本,开辟一个新的内存地址

z = x.copy()
print(z)

[[  1   2   3]
 [  4 999   6]
 [  7   8   9]]
 
z[1,1] = 111
print(z)

# [[  1   2   3]
# [  4 111   6]
# [  7   8   9]]
 
print(x)

# [[  1   2   3]
# [  4 999   6]
# [  7   8   9]]

再来试一下二维数组

ndarray 的切片返回的是对原数据内存地址的引用

x = np.arange(11,36).reshape(5,-1)
print(x)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]
 
y = x

y[::2,:3:2] = -1
print(y)

# [[-1 12 -1 14 15]
# [16 17 18 19 20]
# [-1 22 -1 24 25]
# [26 27 28 29 30]
# [-1 32 -1 34 35]]

print(x)
# [[-1 12 -1 14 15]
# [16 17 18 19 20]
# [-1 22 -1 24 25]
# [26 27 28 29 30]
# [-1 32 -1 34 35]]

copy() 返回的是数组的副本

x = np.arange(11,36).reshape(5,-1)
y = x.copy()

y[::2,:3:2] = -1
print(y)

# [[-1 12 -1 14 15]
# [16 17 18 19 20]
# [-1 22 -1 24 25]
# [26 27 28 29 30]
# [-1 32 -1 34 35]]
 
print(x)

# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]
# [26 27 28 29 30]
# [31 32 33 34 35]]