NumPy索引、切片与重塑

一、基础索引与切片

1. 一维数组(类似Python列表)

python

import numpy as np

arr = np.arange(10)  # [0 1 2 3 4 5 6 7 8 9]
print(arr[5])        # 5 → 获取第6个元素
print(arr[2:7])      # [2 3 4 5 6] → 切片
print(arr[::2])      # [0 2 4 6 8] → 步长为2
print(arr[-3:])      # [7 8 9] → 后三个元素

2. 多维数组索引

python

# 创建2D数组
matrix = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])

# 单个元素访问
print(matrix[1, 2])    # 6 → 第2行第3列
print(matrix[1][2])    # 6 → 等效写法

# 整行整列访问
print(matrix[1])       # [4 5 6] → 第2行
print(matrix[:, 1])    # [2 5 8] → 第2列

二、高级切片技巧

1. 多维度切片

python

matrix = np.arange(16).reshape(4, 4)
'''
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
'''

# 同时切片行和列
print(matrix[1:3, 0:2])
'''
[[4 5]
 [8 9]]
'''

# 混合使用
print(matrix[:2, -1])      # [3 7] → 前两行的最后一列
print(matrix[::2, ::2])    # 每隔一行一列选取
'''
[[ 0  2]
 [ 8 10]]
'''

2. 使用省略号(...

python

arr_3d = np.arange(24).reshape(2, 3, 4)

# 访问所有维度的所有元素
print(arr_3d[..., 0])  # 所有维度的第1列
print(arr_3d[0, ...])  # 第1个维度的所有元素
print(arr_3d[..., 1:3])  # 所有维度的第2-3列

三、布尔索引(重要!)

python

arr = np.array([1, 2, 3, 4, 5, 6])

# 创建布尔数组
mask = arr > 3
print(mask)           # [False False False True True True]
print(arr[mask])      # [4 5 6]

# 直接使用条件
print(arr[arr % 2 == 0])  # [2 4 6] → 偶数

# 多条件组合
condition = (arr > 2) & (arr < 6)
print(arr[condition])     # [3 4 5]

二维数组的布尔索引

python

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

# 条件筛选
print(matrix[matrix > 5])  # [6 7 8 9]

# 按行条件筛选
mask = matrix.sum(axis=1) > 10  # 行的和大于10
print(matrix[mask])             # 输出符合条件的行
'''
[[4 5 6]
 [7 8 9]]
'''

四、花式索引(Fancy Indexing)

1. 整数数组索引

python

arr = np.array([10, 20, 30, 40, 50])
indices = [0, 2, 4]
print(arr[indices])  # [10 30 50]

# 使用多个索引数组(返回笛卡尔积)
rows = [0, 1, 2]
cols = [1, 0, 2]
print(matrix[rows, cols])  # [2, 4, 9]

2. 多维花式索引

python

matrix = np.arange(12).reshape(3, 4)
'''
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
'''

# 选择特定行
print(matrix[[0, 2]])  # 第1和第3行
'''
[[ 0  1  2  3]
 [ 8  9 10 11]]
'''

# 选择特定行和列
print(matrix[[0, 2], :][:, [1, 3]])
'''
[[ 1  3]
 [ 9 11]]
'''

五、重塑操作(Reshaping)

1. reshape() – 改变形状(不改变数据)

python

arr = np.arange(12)
print(arr.reshape(3, 4))  # 3行4列
print(arr.reshape(2, 3, 2))  # 2个3x2矩阵

# 自动推断维度
print(arr.reshape(3, -1))  # -1表示自动计算

2. resize() – 改变形状并修改原数组

python

arr = np.array([1, 2, 3, 4, 5, 6])
arr.resize(2, 3)  # 原地修改
print(arr)
'''
[[1 2 3]
 [4 5 6]]
'''

3. flatten() 和 ravel() – 展平数组

python

matrix = np.array([[1, 2], [3, 4]])

# flatten(): 返回副本
flat_copy = matrix.flatten()
flat_copy[0] = 99
print(matrix)  # 原数组不变

# ravel(): 返回视图(修改会影响原数组)
ravel_view = matrix.ravel()
ravel_view[0] = 99
print(matrix)  # 原数组改变!

六、维度操作

1. 增加/减少维度

python

arr = np.array([1, 2, 3])

# 增加维度
print(arr[np.newaxis, :])  # shape: (1, 3)
print(arr[:, np.newaxis])  # shape: (3, 1)
'''
[[1]
 [2]
 [3]]
'''

# 使用expand_dims
print(np.expand_dims(arr, axis=0))  # 在第0维增加维度
print(np.expand_dims(arr, axis=1))  # 在第1维增加维度

# 压缩维度
arr_2d = np.array([[1], [2], [3]])
print(np.squeeze(arr_2d))  # [1 2 3]

2. 转置与轴交换

python

matrix = np.arange(6).reshape(2, 3)
'''
[[0 1 2]
 [3 4 5]]
'''

print(matrix.T)  # 转置
'''
[[0 3]
 [1 4]
 [2 5]]
'''

arr_3d = np.arange(24).reshape(2, 3, 4)
print(np.transpose(arr_3d, (1, 0, 2)))  # 交换轴

七、高级重塑技巧

1. C(行优先)和 F(列优先)顺序

python

arr = np.arange(12)

# C顺序(默认,行优先)
print(arr.reshape(3, 4, order='C'))
'''
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
'''

# F顺序(列优先)
print(arr.reshape(3, 4, order='F'))
'''
[[ 0  3  6  9]
 [ 1  4  7 10]
 [ 2  5  8 11]]
'''

2. 堆叠与拆分

python

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 水平堆叠
print(np.hstack([a, b]))  # [1 2 3 4 5 6]
print(np.column_stack([a, b]))
'''
[[1 4]
 [2 5]
 [3 6]]
'''

# 垂直堆叠
print(np.vstack([a, b]))
'''
[[1 2 3]
 [4 5 6]]
'''

# 拆分数组
arr = np.arange(9).reshape(3, 3)
print(np.hsplit(arr, 3))  # 水平拆分成3部分
print(np.vsplit(arr, 3))  # 垂直拆分成3部分

八、实用示例

图像处理中的切片

python

# 假设有一个彩色图像 (高度, 宽度, 通道)
image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)

# 裁剪中心区域
cropped = image[20:80, 20:80, :]

# 提取红色通道
red_channel = image[:, :, 0]

# 提取图像的一半
half_image = image[::2, ::2, :]  # 每隔一个像素取一个

数据清洗

python

data = np.random.randn(100, 5)

# 处理异常值
data_cleaned = data.copy()
data_cleaned[data_cleaned > 3] = 3  # 限制最大值
data_cleaned[data_cleaned < -3] = -3  # 限制最小值

# 选择特定列的数据
selected = data[:, [0, 2, 4]]  # 选择第1、3、5列

重要注意事项

  1. 视图 vs 副本:大多数切片操作返回视图(view),修改会影响原数组
  2. 使用copy()获取副本arr_copy = arr[1:3].copy()
  3. 内存布局order='C'order='F'影响性能
  4. 广播规则:重塑时需确保元素总数不变

掌握这些操作是高效使用NumPy的关键!