numpy 的索引与切片,副本与视图
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]]