NumPy数组切片(Slicing)

NumPy是Python中用于科学计算的一个库,它提供了对大规模多维数组和矩阵的支持。切片(slicing)是从这些数组中提取子数组的一个强大工具。

基本切片语法

基本的切片语法是start:stop:step,它可以用于一维和多维数组。让我们一步步来理解。

一维数组的切片

假设我们有一个一维NumPy数组:

import numpy as np

arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
  • arr[start:stop:step]:选择从索引start到索引stop(不包括stop)的元素,步长为step

示例:

print(arr[2:7])      # [2 3 4 5 6]
print(arr[2:7:2])    # [2 4 6]
print(arr[:5])       # [0 1 2 3 4]
print(arr[5:])       # [5 6 7 8 9]
print(arr[::2])      # [0 2 4 6 8]
print(arr[::-1])     # [9 8 7 6 5 4 3 2 1 0]  逆序
多维数组的切片

对于多维数组,切片操作适用于每一个维度。假设我们有一个二维数组:

arr_2d = np.array([
    [0, 1, 2, 3],
    [4, 5, 6, 7],
    [8, 9, 10, 11]
])
  • arr_2d[row_start:row_stop:row_step, col_start:col_stop:col_step]:可以同时对行和列进行切片操作。

示例:

print(arr_2d[:2, :3])       # 前两行和前三列
# [[0 1 2]
#  [4 5 6]]

print(arr_2d[1:, 2:])       # 从第二行开始到最后一行,从第三列开始到最后一列
# [[ 6  7]
#  [10 11]]

print(arr_2d[:, 1:3])       # 所有行,第二列到第三列
# [[ 1  2]
#  [ 5  6]
#  [ 9 10]]

print(arr_2d[::2, ::2])     # 隔行隔列取值
# [[ 0  2]
#  [ 8 10]]

具体示例与解释

为了更好地理解这些操作,让我们再详细看一些具体的示例。

提取特定行和列

从一个二维数组中提取特定的行和列:

print(arr_2d[1, :])   # 提取第二行
# [4 5 6 7]

print(arr_2d[:, 2])   # 提取第三列
# [ 2  6 10]
提取特定区域

我们可以通过组合行和列的切片来提取特定的区域:

print(arr_2d[1:3, 1:3])  # 提取从第二行到第三行,从第二列到第三列的区域
# [[ 5  6]
#  [ 9 10]]

高级切片

除了基础的切片,NumPy还支持一些高级切片技术,如布尔索引和花式索引(fancy indexing)。

布尔索引

布尔索引使用布尔数组来选择数组中的元素:

arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
bool_idx = arr > 5

print(arr[bool_idx])  # 选择大于5的元素
# [6 7 8 9]

# 也可以直接在索引中使用条件表达式
print(arr[arr % 2 == 0])  # 选择偶数
# [0 2 4 6 8]
花式索引

花式索引允许使用整数数组进行索引:

arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
idx = [1, 3, 5, 7]

print(arr[idx])  # 选择索引1, 3, 5, 7处的元素
# [1 3 5 7]

对于多维数组,同样适用:

arr_2d = np.array([
    [0, 1, 2, 3],
    [4, 5, 6, 7],
    [8, 9, 10, 11]
])

row_idx = [0, 2]
col_idx = [1, 3]

print(arr_2d[row_idx, col_idx])  # 选择(0, 1)和(2, 3)位置的元素
# [ 1 11]

结合使用

切片、布尔索引和花式索引可以结合使用以实现复杂的数据提取:

arr = np.array([
    [0, 1, 2, 3],
    [4, 5, 6, 7],
    [8, 9, 10, 11],
    [12, 13, 14, 15]
])

# 提取偶数行的前两列
print(arr[::2, :2])
# [[ 0  1]
#  [ 8  9]]

# 使用布尔索引提取大于5的元素
print(arr[arr > 5])
# [ 6  7  8  9 10 11 12 13 14 15]

# 花式索引提取指定行和列
print(arr[[0, 2], [1, 3]])
# [ 1 11]

实际应用中的例子

假设有一个包含训练数据的二维数组train_data,它的最后一列是目标变量,我们希望提取特征数据和目标变量:

import numpy as np

train_data = np.array([
    [1.0, 2.0, 3.0, 10.0],
    [4.0, 5.0, 6.0, 20.0],
    [7.0, 8.0, 9.0, 30.0]
])

# 提取目标变量(最后一列)
y_train = train_data[:, -1]
print("y_train:", y_train)
# [10. 20. 30.]

# 提取特征数据(除最后一列外的所有列)
raw_x_train = train_data[:, :-1]
print("raw_x_train:\n", raw_x_train)
# [[1. 2. 3.]
#  [4. 5. 6.]
#  [7. 8. 9.]]

这个例子展示了如何使用切片从数据集中提取目标变量和特征数据。

结论

NumPy切片是一种强大且灵活的工具,用于从数组中提取子集。理解这些基本概念和操作对于高效处理和操作数据非常重要。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐