NumPy 布尔索引与花式索引详解
NumPy 数组索引包括普通索引、切片索引、布尔索引和花式索引。布尔索引通过条件筛选数据,花式索引通过位置数组访问元素。两者都是高级索引,返回副本而非视图。下面通过代码实例深入解析。
1. 布尔索引:基于条件的数据筛选
布尔索引使用布尔数组(True/False)作为掩码,筛选满足条件的元素。布尔数组必须与原数组形状一致。
底层原理:NumPy 将布尔数组转换为整数索引列表(如 [False, True]
→ 索引 [1]
),然后提取对应元素,生成新数组(副本)。
示例 1:一维数组布尔索引
import numpy as np
# 创建一维数组
arr = np.array([10, 20, 30, 40, 50])
# 生成布尔掩码:筛选大于25的元素
mask = arr > 25 # 输出:[False, False, True, True, True]
# 应用布尔索引:提取True位置的元素
result = arr[mask] # 输出:[30, 40, 50]
print("布尔索引结果:", result)
示例 2:多维数组布尔索引
# 创建2x3二维数组
matrix = np.array([[1, 2, 3], [4, 5, 6]])
# 生成布尔掩码:筛选大于3的元素
mask = matrix > 3 # 输出:[[False, False, False], [True, True, True]]
# 应用布尔索引:结果展平为一维数组
result = matrix[mask] # 输出:[4, 5, 6]
print("多维布尔索引结果:", result)
# 链式条件示例:筛选大于2且小于5的元素
mask_chain = (matrix > 2) & (matrix < 5) # &表示逻辑AND
result_chain = matrix[mask_chain] # 输出:[3, 4]
print("链式条件结果:", result_chain)
2. 花式索引:按位置访问元素
花式索引使用整数数组指定要访问的元素位置,支持不连续访问。返回副本而非视图。
底层原理:NumPy 将索引数组转换为 ndarray
,通过 np.take()
复制数据到新数组。
与切片区别:
- 花式索引:返回副本,支持不连续位置(如
[0, 2]
)。 - 切片索引:返回视图,仅支持连续位置(如
[1:3]
)。
示例 3:一维数组花式索引
# 创建一维数组
arr = np.array([10, 20, 30, 40, 50])
# 指定索引位置:[1]和[3]
indices = np.array([1, 3]) # 整数数组
# 应用花式索引:按indices顺序提取元素
result = arr[indices] # 输出:[20, 40]
print("花式索引结果:", result)
# 修改结果不影响原数组(副本特性)
result[0] = 100
print("修改后原数组:", arr) # 输出仍为[10,20,30,40,50]
示例 4:多维数组花式索引
# 创建3x3二维数组
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 指定行索引[0,2]和列索引[1,0]
row_indices = [0, 2] # 行位置
col_indices = [1, 0] # 列位置
# 应用花式索引:提取(0,1)和(2,0)位置的元素
result = matrix[row_indices, col_indices] # 输出:[2, 7]
print("多维花式索引结果:", result)
3. 组合布尔索引与花式索引
结合两者可处理复杂筛选逻辑。注意:链式操作可能生成临时副本,增加内存开销。
示例 5:组合索引实战
# 创建3x3数组
arr = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
# 目标:筛选第0行和第1行中大于25的元素
# 步骤1:花式索引选择行(返回副本)
rows = [0, 1] # 选择第0行和第1行
sub_arr = arr[rows] # 子数组:[[10,20,30], [40,50,60]]
# 步骤2:布尔索引筛选大于25的元素
mask = sub_arr > 25 # 掩码:[[False,False,True], [True,True,True]]
result = sub_arr[mask] # 输出:[30, 40, 50, 60]
print("组合索引结果:", result)
4. 关键注意事项
-
副本 vs 视图:布尔/花式索引始终返回副本。修改副本不影响原数组。
-
广播对齐:布尔数组形状必须与原数组一致,否则报错。
# 错误示例:形状不匹配 try: mask = np.array([True, False]) result = arr[mask] # 报错:布尔数组形状(2,)与数组形状(5,)不匹配 except Exception as e: print("错误:", e)
-
顺序问题:花式索引结果严格按索引数组顺序(如
[2,0]
返回[arr[2], arr[0]]
)。 -
内存优化:避免在大数据集上链式操作(如
arr[indices][mask]
),减少副本生成。 -
布尔索引:用于条件筛选(如
arr[arr > 10]
),适合数据清洗。 -
花式索引:用于位置访问(如
arr[[1,3]]
),适合提取非连续数据。 -
核心区别:花式索引支持任意位置,布尔索引依赖条件。