Python高级特性:详解多维数组切片(Slice)
1. 多维数组切片基本用法
切片是 Python 中常用的一种操作,可以用来切分列表、字符串、元组等序列型数据,多维数组也不例外。对于二维数组,切片只需在索引号中加入" : "符号,即可切分整行或整列。而对于多维数组,我们可以在切片表达式中使用多个" : "符号,来对各个维度进行切片。
下面是一个基本的多维数组切片例子:
import numpy as np
a = np.array([ # 创建一个二维数组
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(a[1:3, 1:3]) # 取数组的第2-3行和第2-3列
以上代码的输出结果为:
[[5 6]
[8 9]]
在切片表达式 a[1:3, 1:3] 中,第1个":"符号前后的数字表示在第1个维度上,要取从第2个元素到第4个元素中间的子数组;第2个":"符号前后的数字则表示在第2个维度上,要取从第2个元素到第4个元素中间的子数组。由于每个维度都有2个终止切片,所以最终得到的是一个2x2的子数组。
2. 多维数组切片进阶用法
2.1 使用省略号(...)代替多个":"符号
当我们要切片的维度较多时,可以使用省略号(...)代替多个":"符号,如下所示:
import numpy as np
a = np.arange(27).reshape((3, 3, 3)) # 创建一个三维数组
print(a[..., 1]) # 取第2列的值
print(a[1, ...]) # 取第2行的值,这里...后面默认是“:”: a[1, :, :]
print(a[..., :2, :2]) # 取每个维度前两行和前两列的值
以上代码的输出结果为:
[[ 1 4 7]
[10 13 16]
[19 22 25]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[[ 0 1]
[ 3 4]]
[[ 9 10]
[12 13]]
[[18 19]
[21 22]]]
2.2 使用负数索引和步长来切片
除了使用一个":"符号来表示所要切片的整个范围,我们还可以使用负数索引和步长来定义切片。
- 使用负数索引
负数索引表示从数组的末尾开始往前数的元素。例如,a[-1]表示数组的最后一个元素,a[-2]表示倒数第二个元素。我们可以在切片中使用负数索引来取反向的子数组,如下所示:
import numpy as np
a = np.array([[1, 2], [3, 4], [5, 6]])
print(a[-1]) # 取最后一行
print(a[:,-1]) # 取最后一列
print(a[::-1]) # 反向输出整个数组
以上代码的输出结果为:
[5 6]
[2 4 6]
[[5 6]
[3 4]
[1 2]]
- 使用步长
步长表示每隔多少个元素取一个值。可以使用":"符号和步长值一起快速切分一个大数组,如下所示:
import numpy as np
a = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
print(a[::2]) # 每隔一个元素取一行
以上代码的输出结果为:
[[ 1 2]
[ 5 6]
[ 9 10]]
3. 多维数组切片进阶应用举例
3.1 将彩色图片转成灰度图
我们知道,彩色图片是由R,G,B三种颜色的像素值组成的,而灰度图像则是只使用灰度值来表示像素的图像。下面是一个将彩色图片转成灰度图的例子:
from PIL import Image
import numpy as np
# 加载图片并转成numpy数组
img = Image.open('pic.jpg').convert('RGB')
img_arr = np.array(img)
# 将RGB三种颜色的像素值加权平均,得到灰度图
gray_arr = np.dot(img_arr[...,:3], [0.299, 0.587, 0.114])
# 将灰度值都限制在0-255之间,防止显示异常
gray_arr = np.clip(gray_arr, 0, 255)
# 转成灰度图
gray_img = Image.fromarray(gray_arr.astype('uint8'))
gray_img.show()
上面的代码中,我们使用PIL库读取图片并转成numpy数组。由于图像是RGB格式的,因此我们只需要取出前3个通道的像素值,然后对其加权平均,得到灰度值。此时,灰度值可能会超过范围(0-255),因此我们再使用np.clip()函数将其限制在0-255之间。最后,我们将灰度值转成整数类型,并使用Image.fromarray()函数将其转成灰度图。运行上述代码,会将彩色图像转化成灰度图。
3.2 使用切片做向量旋转
在游戏开发中,经常需要对游戏对象进行旋转操作。下面是一个使用切片实现向量旋转的例子:
import numpy as np
# 定义一个向量
v = np.array([1, 2])
# 将向量每个维度都乘上一个旋转矩阵,得到新的向量
theta = np.pi / 2
rotate_mat = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
rotated_v = np.dot(v, rotate_mat)
print(rotated_v) # [-2. 1.]
上述代码中,我们首先定义了一个向量 v。然后,我们构造一个以原点为中心,逆时针旋转90度的旋转矩阵,将其命名为rotate_mat。旋转矩阵是一个2x2的矩阵,旋转后的坐标可表示为 旋转矩阵 * 原坐标。我们使用np.dot()函数将向量v和旋转矩阵相乘,得到旋转后的向量rotated_v。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python高级特性——详解多维数组切片(Slice) - Python技术站