一、Python与Numpy切片操作的异同
Python 原生的列表切片操作和 NumPy 数组的切片操作有相似之处,但在功能、性能和应用范围上存在一些关键差异。接下来将详细分析它们的不同点,并分别介绍它们的用法。
1. 基本概念与用法
Python 列表的切片操作:
Python 列表的切片是通过指定起始、结束和步长的方式来获取原列表的一个子列表。它遵循以下格式:
list[start:stop:step]
start
:切片开始的索引,包含在切片结果中。stop
:切片结束的索引,但不包含在切片结果中。step
:切片的步长,默认为 1。
示例:
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 获取索引 2 到 5 的元素
print(my_list[2:6]) # 输出:[2, 3, 4, 5]
# 获取从 0 到结尾,每隔两个元素取一个
print(my_list[::2]) # 输出:[0, 2, 4, 6, 8]
# 反向切片
print(my_list[::-1]) # 输出:[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
NumPy 数组的切片操作:
NumPy 的切片操作类似于 Python 列表,但它可以处理多维数组,并且由于 NumPy 的底层实现,切片通常不会生成新的数组,而是返回原数组的视图。这意味着对切片结果的修改会影响原数组中的数据。
基本格式与 Python 列表相同:
array[start:stop:step]
示例:
import numpy as np
# 创建一个 1D NumPy 数组
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 获取索引 2 到 5 的元素
print(arr[2:6]) # 输出:[2 3 4 5]
# 获取从 0 到结尾,每隔两个元素取一个
print(arr[::2]) # 输出:[0 2 4 6 8]
# 反向切片
print(arr[::-1]) # 输出:[9 8 7 6 5 4 3 2 1 0]
2. Python 列表 vs. NumPy 数组切片的不同点
2.1 返回对象
- Python 列表:切片操作返回的是一个新列表,与原列表没有联系。对切片结果的修改不会影响原列表。
- NumPy 数组:切片操作返回的是原数组的视图(view),而不是新数组。这意味着对切片结果的修改会影响原数组中的数据。
示例:
# Python 列表
my_list = [0, 1, 2, 3, 4, 5]
slice_list = my_list[2:5]
slice_list[0] = 99
print(my_list) # 输出:[0, 1, 2, 3, 4, 5](原列表不变)
# NumPy 数组
arr = np.array([0, 1, 2, 3, 4, 5])
slice_arr = arr[2:5]
slice_arr[0] = 99
print(arr) # 输出:[ 0 1 99 3 4 5](原数组被修改)
原因:NumPy 为了效率,默认通过切片操作返回的是视图而非副本。Python 列表则返回一个新的列表,原始列表不会受影响。
2.2 多维切片支持
- Python 列表:仅支持一维切片操作,对于多维嵌套列表,必须分别索引每一维度的元素,无法同时切片多个维度。
- NumPy 数组:可以直接对多维数组进行切片操作,支持在每一个维度上同时进行索引和切片。
示例:
# Python 多维列表的访问
my_list = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
# Python 列表不能一次性切片多个维度
print(my_list[0:2]) # 输出:[[0, 1, 2], [3, 4, 5]](只能切片第一维)
# NumPy 多维数组的切片
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
# NumPy 支持对多维数组进行切片
print(arr[0:2, 1:3]) # 输出:[[1 2] [4 5]]
2.3 步长
- Python 列表:切片支持正步长和负步长。
- NumPy 数组:同样支持正步长和负步长,但 NumPy 提供了更多功能,支持对多维数组的每一维度使用不同的步长。
示例:
# Python 列表正步长和负步长
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(my_list[1:8:2]) # 输出:[1, 3, 5, 7]
print(my_list[8:1:-2]) # 输出:[8, 6, 4, 2]
# NumPy 数组步长
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
# 对不同维度使用不同的步长
print(arr[::2, ::2]) # 输出:[[0 2] [6 8]](两维度上步长都是 2)
2.4 高级索引
- Python 列表:原生不支持布尔索引或整数数组索引。
- NumPy 数组:支持布尔索引和整数数组索引,可以非常灵活地提取数据。
示例:
import numpy as np
# 创建一个 NumPy 数组
arr = np.array([10, 20, 30, 40, 50])
# 布尔索引
print(arr[arr > 30]) # 输出:[40 50]
# 整数数组索引
indices = np.array([0, 2, 4])
print(arr[indices]) # 输出:[10 30 50]
3. NumPy 的高级切片功能
3.1 布尔切片
NumPy 支持布尔切片,可以通过布尔条件筛选数组中的元素。
示例:
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(arr[arr > 5]) # 输出:[ 6 7 8 9 10]
3.2 整数数组切片
NumPy 支持用整数数组对原数组进行切片,灵活地选择多个元素。
示例:
arr = np.array([10, 20, 30, 40, 50])
index_arr = np.array([1, 3])
print(arr[index_arr]) # 输出:[20 40]
3.3 花式索引
NumPy 支持使用多个整数数组对多维数组进行“花式索引”。
示例:
arr = np.array([[1, 2], [3, 4], [5, 6]])
rows = np.array([0, 1, 2])
cols = np.array([1, 0, 1])
print(arr[rows, cols]) # 输出:[2 3 6]
总结
特性 | Python 列表 | NumPy 数组 |
---|---|---|
返回结果 | 返回新列表 | 返回原数组的视图,数据共享 |
多维切片 | 只支持一维切片 | 支持多维数组的切片操作 |
步长 | 支持正步长和负步长 | 支持正负步长,且可以对每一维度使用不同步长 |
高级索引(布尔、整数索引) | 不支持 | 支持布尔索 |
在 NumPy 中,整数索引(也称为整型数组索引)是一种强大的功能,允许你通过一个或多个整数数组来访问或修改数组中的特定元素。通过整数索引,你可以根据数组中的位置快速提取所需的数据。
二、整数索引的使用
1. 基本整数索引
NumPy 中最常见的索引方式是使用单个整数或一组整数来访问数组元素。这种方式与 Python 的列表索引类似。
示例:
import numpy as np
# 创建一个 2D 数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 访问某个元素,例如获取第一行第二列的元素
print(arr[0, 1]) # 输出:2
2. 使用整型数组进行索引
你可以使用整型数组对 NumPy 数组的多个元素进行索引。整型数组中的每个元素对应原始数组的索引位置。
示例:
import numpy as np
# 创建一个 1D 数组
arr = np.array([10, 20, 30, 40, 50])
# 使用整型数组进行索引
index = np.array([0, 2, 4]) # 想要访问的索引
print(arr[index]) # 输出:[10 30 50]
3. 多维数组中的整型数组索引
对于多维数组,你可以提供多个整型数组来同时索引不同维度。
示例:
import numpy as np
# 创建一个 2D 数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 使用整型数组进行多维索引
row_indices = np.array([0, 1, 2])
col_indices = np.array([2, 1, 0])
# 提取指定位置的元素
print(arr[row_indices, col_indices]) # 输出:[3 5 7]
在这个例子中,arr[0, 2]
,arr[1, 1]
,arr[2, 0]
对应的元素分别是 3
,5
和 7
。
4. 整数索引与切片的组合
你可以将整数索引与切片操作组合使用,以便选择多个维度上的特定元素。
示例:
import numpy as np
# 创建一个 3D 数组
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
# 使用整型索引和切片的组合
print(arr[1, :, 1]) # 输出:[6 8]
在这个例子中,1
是整型索引,表示选择第二个子数组;:
是切片,表示选取所有行;1
是第二列的元素。
5. 修改数组中的元素
整数索引不仅可以用于提取元素,还可以通过它直接修改数组中的某些元素。
示例:
import numpy as np
# 创建一个 1D 数组
arr = np.array([10, 20, 30, 40, 50])
# 使用整数索引修改元素
arr[[0, 2, 4]] = 99 # 将索引 0, 2, 4 的元素都改为 99
print(arr) # 输出:[99 20 99 40 99]
6. 布尔索引与整数索引的结合
你也可以将布尔索引与整数索引结合使用,以更灵活地筛选和修改数据。
示例:
import numpy as np
# 创建一个数组
arr = np.array([10, 20, 30, 40, 50])
# 使用布尔索引和整数索引筛选并修改数据
arr[arr > 30] = -1 # 将大于 30 的元素修改为 -1
print(arr) # 输出:[10 20 30 -1 -1]
总结:
在 NumPy 中,整数索引是一种高效且灵活的操作手段,能够帮助你根据指定的位置访问、提取或修改数组中的数据。通过整型数组索引、多维索引、切片的组合使用,你可以轻松地处理复杂的数据提取任务。
三、索引时逗号’,'的使用
在 NumPy 中,切片操作中的逗号(,
)用来分隔不同维度的索引。当你对多维数组进行切片时,逗号用于区分每个维度的切片规则。
1. 基本概念
对于多维数组,逗号的作用是让你可以同时对不同维度进行索引或切片。
- 在一维数组中,不需要逗号,因为只有一个维度。
- 在二维数组中,逗号用于区分行和列的切片。
- 在三维或更高维数组中,逗号用于区分每个维度。
每个逗号前后的索引或切片分别对应 NumPy 数组的一个维度。
2. 示例说明
2.1 一维数组(无需逗号)
一维数组只需要一个切片,不涉及维度间的区分。
import numpy as np
arr = np.array([0, 1, 2, 3, 4, 5])
# 获取索引 2 到 4(不包含 4)的元素
print(arr[2:4]) # 输出:[2 3]
2.2 二维数组(行和列的切片)
在二维数组中,逗号分隔行和列的切片。
import numpy as np
# 创建一个 3x3 的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 获取第 1 行、第 2 列的元素
print(arr[1, 2]) # 输出:6
# 获取第 0 行到第 1 行(不包括第 2 行),以及所有列
print(arr[0:2, :]) # 输出:
# [[1 2 3]
# [4 5 6]]
# 获取所有行,第 1 列到第 2 列(不包括第 3 列)
print(arr[:, 1:3]) # 输出:
# [[2 3]
# [5 6]
# [8 9]]
2.3 三维数组
在三维数组中,逗号可以用来区分层、行、和列。对于一个三维数组,切片 arr[i, j, k]
的含义是:
i
表示层(第 0 维)j
表示行(第 1 维)k
表示列(第 2 维)
import numpy as np
# 创建一个 3x3x3 的三维数组
arr_3d = np.arange(27).reshape(3, 3, 3)
# 获取第 0 层的第 1 行第 2 列的元素
print(arr_3d[0, 1, 2]) # 输出:5
# 获取所有层的第 0 行
print(arr_3d[:, 0, :]) # 输出:
# [[ 0 1 2]
# [ 9 10 11]
# [18 19 20]]
# 获取第 1 层的所有行和列
print(arr_3d[1, :, :]) # 输出:
# [[ 9 10 11]
# [12 13 14]
# [15 16 17]]
2.4 不同维度的切片组合
NumPy 允许对每个维度指定不同的切片范围,并通过逗号分隔。你可以为每个维度提供具体的切片范围、索引或切片步长。
import numpy as np
arr_3d = np.arange(27).reshape(3, 3, 3)
# 获取第 1 层的前 2 行,前 2 列的子数组
print(arr_3d[1, 0:2, 0:2]) # 输出:
# [[ 9 10]
# [12 13]]
# 获取所有层,步长为 2 的行,步长为 2 的列
print(arr_3d[:, ::2, ::2]) # 输出:
# [[[ 0 2]
# [ 6 8]]
# [[ 9 11]
# [15 17]]
# [[18 20]
# [24 26]]]
3. :
和 ...
的特殊使用
:
:表示从该维度的起点到终点的切片(即选择所有元素)。...
:NumPy 的特殊语法,表示 “任意数量的维度”,可用于忽略一部分维度。
示例:
import numpy as np
arr_3d = np.arange(27).reshape(3, 3, 3)
# 使用 `:` 获取第 1 层的所有行和列
print(arr_3d[1, :, :]) # 输出:
# [[ 9 10 11]
# [12 13 14]
# [15 16 17]]
# 使用 `...` 获取第 2 列的所有层和行
print(arr_3d[..., 2]) # 输出:
# [[ 2 5 8]
# [11 14 17]
# [20 23 26]]
总结:
- 在 NumPy 中,逗号用来分隔多维数组的不同维度。
- 每个维度可以单独使用切片表达式,允许同时对多个维度进行操作。