从事数据科学和机器学习的人都知道,numpy是必备的工具之一。在numpy中,切片(slicing)是经常用到的操作之一。简单的切片是很容易掌握的,但是当涉及到多维数组,或者需要高效地选择元素时,我们就需要更加高效和优美的numpy切片技巧。
一、基础的切片操作
要理解高级切片技巧,首先需要掌握numpy基础切片操作。以一维数组为例:
import numpy as np
array = np.array([1, 2, 3, 4, 5])
# 选择第2到第4个元素
array[1:4] #=> array([2, 3, 4])
# 从第2个元素起,每隔一个取一个元素
array[1:4:2] #=> array([2, 4])
# 可以用负数索引
array[-2:] #=> array([4, 5])
在切片操作中,冒号(:)用于指定选择范围,第一个数表示起始位置(包含),第二个数表示结束位置(不包含),第三个数表示步长。
对于多维数组,每个维度可以分别进行切片:
array = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
# 选择第1行
array[0] #=> array([1, 2, 3])
# 选择第1、2行
array[:2] #=> array([[1, 2, 3],
[4, 5, 6]])
# 选择第2列
array[:, 1] #=> array([2, 5, 8])
# 选择第1、2行,第2、3列
array[:2, 1:] #=> array([[2, 3],
[5, 6]])
二、布尔型切片
numpy允许使用布尔型数组进行切片。例如,我们可以选择满足某个条件的所有元素。
array = np.array([1, 2, 3, 4, 5])
mask = array % 2 == 0
array[mask] #=> array([2, 4])
对于多维数组,我们可以使用多维布尔型数组进行切片。例如,选择所有大于5的元素:
array = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
mask = array > 5
array[mask] #=> array([6, 7, 8, 9])
三、花式索引
花式索引(fancy indexing)指的是通过整数数组或布尔型数组选择数组中的元素。与切片不同,花式索引会复制选取的元素,而不是引用它们。
array = np.array([1, 2, 3, 4, 5])
# 选择第1、3、5个元素
indices = [0, 2, 4]
array[indices] #=> array([1, 3, 5])
对于多维数组,我们可以使用多个整数数组或一个布尔型数组选择元素。例如,选择第1、3行和第2、3列的元素:
array = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
# 选择第1、3行和第2、3列的元素
indices_row = [0, 2]
indices_col = [1, 2]
array[indices_row][: ,indices_col] #=> array([[2, 3],
[8, 9]])
四、组合切片技巧
最后,我们可以将基础切片、布尔型切片和花式索引结合起来,实现更加高效、灵活的切片操作。
例如,选择第偶数行,第奇数列的元素:
array = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
# 选择第偶数行,第奇数列
mask_row = np.array([False, True, False, True])
mask_col = np.array([True, False, True])
array[mask_row][:, mask_col] #=> array([[2],
[8]])
五、总结
在numpy中,切片是一种非常基础和常用的操作。高效、优美的切片技巧可以大大提高代码的可读性和执行效率。在实践中,我们应该灵活地运用基础切片、布尔型切片、花式索引和组合切片技巧,根据不同情况选择最合适的方式。