NumPy - 切片
切片是从 NumPy 数组中提取数据子集的方法。它可以在 NumPy 数组的一个或多个维度上执行。我们可以通过使用 [start : end] 以及数组名称指定起始和结束索引值来定义要切片的数组部分。
切片也可以使用 Python 的内置函数 slice 对象,该对象由相同的 start、stop 和 step 参数构造,用于定义范围。此切片对象将传递给数组以提取数组的一部分。
切片数组的语法为 [start:stop:step],其中 -
Start 是切片对象开始的索引(包含索引)。如果我们不指定 start,则默认情况下,它将被视为 '0'。
Stop 是切片结束的索引(不包含,即不包含此索引处的元素)。如果我们不指定 stop,默认情况下,它将被视为该维度的数组长度。
Step 决定索引之间的间隔(即跳过多少个元素)。如果我们不指定 step,默认情况下,step 为 1,并且 step 不能为零。
一维 NumPy 数组切片
一维数组切片用于访问特定使用 start:stop:step 参数。它可以高效地设置子集、跳过元素或反转数组。
示例:使用 start:stop:step
让我们创建一个一维数组,其中书架上有一排标有 0 到 9 的书籍,我们需要从第 1 本书到第 8 本书中每隔一本书选取一本书。
在此示例中,我们将用冒号 : (start:stop:step) 分隔的切片参数直接应用于 ndarray 对象。此处起始值为 1(第二本书),停止值为 8(在第八本书之前结束),步长为 2,即在索引之间每隔一本书选取一本。
import numpy as np arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) print(arr[1:8:2])
以下是上述代码的输出 -
[1 3 5 7]
示例:使用 Slice 对象
使用内置的 slice 函数可以实现与示例 1 相同的结果。代码如下:-
import numpy as np arr = np.arange(10) s = slice(1,8,2) print(arr[s])
上述代码的输出如下:-
[1 3 5 7]
示例:使用起始参数进行切片
从索引开始切片。当我们仅使用起始参数时,它将从该索引开始,由于我们默认未指定终止参数,因此它将考虑数组的长度 -
import numpy as np a = np.arange(10) print(a[2:])
以下是上述代码的输出 -
[2 3 4 5 6 7 8 9]
示例:使用终止参数进行切片
仅使用终止参数进行切片。当我们仅使用终止参数并省略起始参数时,它将访问从数组开头到指定终止索引(但不包括该索引)的元素。代码如下:-
import numpy as np a = np.arange(10) print(a[:7])
以上代码的输出如下:-
[0 1 2 3 4 5 6]
示例:使用 Step 参数
仅使用 step 参数对项目进行切片。由于我们没有指定起始和终止位置,以下代码将从数组的开头到结尾提取每个第二个元素。
import numpy as np a = np.arange(10) print(a[::2])
运行上述程序,结果如下:
[0 2 4 6 8]
二维 NumPy 数组切片
二维 NumPy 数组类似于矩阵,它有两个索引:行和列。切片二维数组的语法与一维数组相同。唯一需要改变的是,我们必须为数组的每个维度定义一个切片。
示例
让我们创建一个二维员工数据数组,其中三列分别包含员工 ID、年龄和薪水。我们将使用切片参数获取员工 2 的信息,并从索引 2 开始获取所有员工的年龄。-
import numpy as np employees = np.array([ [1, 25, 50000], [2, 30, 60000], [3, 28, 55000], [4, 35, 65000], [5, 40, 70000] ]) print("员工 2 的信息:",员工[1]) print("从索引 2 开始的员工年龄:", 员工[2:, 1])
以下是上述代码的输出 -
员工 2 的信息:[ 2 30 60000] 从索引 2 开始的员工年龄:[28 35 40]
三维 NumPy 数组切片
三维数组是二维数组的集合,具有三个索引:深度(或平面)、行和列。三维数组的语法与一维和二维数组相同,但我们需要为所有三个维度定义切片。
示例
我们使用 arange() 函数创建一个三维数组,并使用包含 0 到 23 的值对其进行整形,然后将这个一维数组重塑为三维数组,表示一个 (2*3*4) 矩阵,并使用 slice 对象进行切片,得到一个子数组,该子数组包含第一层(深度)、所有行和前两列 -
import numpy as np arr_3d = np.arange(24).reshape(2, 3, 4) print("原始三维数组: " , arr_3d) subarray = arr_3d[0, :, :2] print(" 切片后子数组:", subarray)
运行上述程序,结果如下:
原始三维数组: [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] 切片子数组:[[0 1] [4 5] [8 9]]
负切片
负索引允许从数组末尾访问元素。索引 -1 表示最后一个元素,-2 表示倒数第二个元素,以此类推。它主要用于需要从数组末尾访问特定元素的情况。它与切片语法(start:stop:step)结合使用,以相反的顺序提取元素。
示例:访问最低 5 分
我们创建一个数组来存储学生成绩,并需要快速识别最低 5 分,我们使用 start 参数进行负切片 -
import numpy as np marks = np.array([93, 87, 98, 89, 67, 65, 54, 32, 21]) print("最低 5 分是:", marks[-5:])
运行上述程序,结果如下 -
最低 5 分是:[67 65 54 32 21]
示例:对每个第二个元素进行切片(逆序)
创建一个一维数组,我们需要从数组末尾开始对每个第二个元素进行切片 -
import numpy as np data=np.array(['H','A','R','R','Y']) print(data[-1::-2])
运行上述程序,结果如下:
['Y' 'R' 'H']
示例:反转数组
我们也可以使用负切片来反转数组。代码如下:-
import numpy as np data=np.array([98,87,86,65,54,32,21]) print("反转数据:", data[::-1])
以上代码的输出如下:-
反转数据:[21 32 54 65 86 87 98]
特殊情况
在 NumPy 中,切片操作有一些特殊情况,可以增强数据操作的灵活性。这些包括用于部分索引的省略号 (...)、用于跨维度访问所有元素的完整切片 (:),以及用于重塑数组的 newaxis。
省略号
切片还可以包含省略号"()",以创建与数组维度长度相同的选择元组。如果在行位置使用省略号,它将返回一个由行中的项目组成的 ndarray。
省略号 (...) 使多维度切片更加容易。它可以使用任意数量的冒号 (:) 来填充未指定的维度。
例如,在三维数组中,a[..., 1] 将选择所有深度和行,但仅选择第二列。
示例:访问特定维度中的项目
让我们创建一个二维数组,并使用省略号对第二列中的所有项目进行切片 -
import numpy as np a = np.array([[1,2,3],[3,4,5],[4,5,6]]) print('第二列中的项目是:', a[...,1] ) print('第二行中的项目是:',a[1,...] ) print('从第一列开始的项目是:',a[...,1:])
以下是上述代码的输出 -
第二列中的项目为:[2 4 5] 第二行中的项目为:[3 4 5] 从第一列开始的项目为:[[2 3] [4 5] [5 6]]
完整切片
完整切片用于使用 (:) 访问数组的所有深度、行和列。让我们看看每个用例的示例
示例:访问行、列和整个数组
让我们创建一个食物评分系统,其中行代表用户,列代表 4 家不同餐厅的评分。
import numpy as np Food_ratings = np.array([ [4, 5, 3, 4], # 用户 1 [3, 4, 2, 5], # 用户 2 [5, 5, 4, 4] # 用户 3 ]) # 获取用户 1 的所有评分 user1 = Food_ratings[0, :] print("用户 1 评分:", user1) # 获取餐厅 1 的所有评分 restuarent_ratings = Food_ratings[:, 0] print("餐厅 1 评分:", restuarent_ratings) # 获取所有评分(整个表格) all_ratings = Food_ratings[:, :] print("所有评分: ", all_ratings)
以下是输出以上代码 −
用户 1 评分:[4 5 3 4] 餐厅 1 评分:[4 3 5] 所有评分: [[4 5 3 4] [3 4 2 5] [5 5 4 4]]
NewAxis
NumPy 中的 Newaxis 函数用于向数组添加新轴,从而增加其维度。它在重塑数组和进行矩阵变换时非常有用。使用 newaxis,可以轻松地将一维数组转换为二维行向量或列向量,反之亦然:将二维数组转换为三维数组等等。
示例:将一维数组转换为二维列向量
创建一个一维数组并将其转换为二维列向量
import numpy as np arr = np.array([1, 2, 3, 4]) print(arr[:, np.newaxis])
以下是上述代码的输出 -
[[1] [2] [3] [4]]
示例:使用 hstack() 合并一维和二维数组
假设有两个一维数组:一个以毫米为单位存储月降雨量,另一个存储月份名称。我们将此一维数组转换为二维数组,并使用 hstack() 函数将两个数组与其横轴连接起来。这个二维数组将保存两个月份的降雨总量。
当我们将其转换为二维数组时,NumPy 会将混合数据类型转换为单一类型。在本例中,结果将是一个字符串数组,因为 Months 数组由字符串组成。因此,对降雨量数组的数值运算将不再有效。
import numpy as np Rainfall = np.array([120, 85, 60, 90, 150]) Months = np.array(['Jan', 'Feb', 'Mar', 'Apr', 'May']) Rainfall_2d = Rainfall[:, np.newaxis] Months_2d = Months[:, np.newaxis] Rainfall_Data = np.hstack((Months_2d, Rainfall_2d)) print("每月降雨量数据:") print(Rainfall_Data)
以下是上述代码的输出 -
月降雨量数据: [['Jan' '120'] ['Feb' '85'] ['Mar' '60'] ['Apr' '90'] ['May' '150']]