NumPy repeat 方法:从基础到高级应用详解
在数据处理和科学计算中,NumPy 是 Python 不可或缺的库。它提供了高效的多维数组对象,以及大量用于操作这些数组的函数。其中,numpy.repeat 是一个非常实用的函数,用于按照指定的次数重复数组中的元素。本文将从基础用法入手,逐步深入到 repeat 方法的高级应用场景,并探讨其与 tile 方法的区别。
1. numpy.repeat 简介
numpy.repeat(a, repeats, axis=None) 函数是用来重复数组 a 中的元素。它有三个主要参数:
a: 输入数组。repeats: 指定每个元素或整个数组重复的次数。它可以是一个整数,也可以是一个数组(序列),其长度必须与axis指定的轴的长度匹配。axis: 可选参数,指定沿着哪个轴重复元素。None(默认值): 将输入数组a展平(flatten)后再进行重复操作,返回一个一维数组。- 整数: 指定沿着该轴重复。例如,
axis=0沿着行重复,axis=1沿着列重复。
理解 repeat 的核心是记住它会重复数组中的元素,而不是像 tile 那样重复整个数组或子数组。
2. 基础用法
2.1 简单重复整个一维数组
当 repeats 是一个整数,且 axis 为 None 或输入数组是一维时,repeat 会将数组中的每个元素重复 repeats 次。
“`python
import numpy as np
arr1d = np.array([1, 2, 3])
每个元素重复 3 次
result1 = np.repeat(arr1d, 3)
print(“Result 1 (each element repeated):”, result1)
Output: [1 1 1 2 2 2 3 3 3]
“`
2.2 重复整个多维数组(展平后)
当 axis=None 时,多维数组会被展平为一维数组,然后其元素按顺序重复。
“`python
arr2d = np.array([[1, 2], [3, 4]])
展平后每个元素重复 2 次
result2 = np.repeat(arr2d, 2, axis=None)
print(“\nResult 2 (flattened, then each element repeated):”, result2)
Output: [1 1 2 2 3 3 4 4]
“`
3. repeats 参数的灵活运用
repeats 参数不仅可以是单个整数,还可以是一个数组或列表,这为元素重复提供了更精细的控制。
3.1 repeats 为整数
当 repeats 是一个整数时,数组中的每个元素(如果 axis 为 None)或沿着指定轴的每个“切片”(如果 axis 指定),都会重复相同的次数。
“`python
沿 axis=0 (行) 重复
result3 = np.repeat(arr2d, 2, axis=0)
print(“\nResult 3 (repeating rows):”)
print(result3)
Output:
[[1 2]
[1 2]
[3 4]
[3 4]]
沿 axis=1 (列) 重复
result4 = np.repeat(arr2d, 2, axis=1)
print(“\nResult 4 (repeating columns):”)
print(result4)
Output:
[[1 1 2 2]
[3 3 4 4]]
``axis
**注意:** 当被指定时,repeats的长度如果是一个序列,则必须与该axis上的元素数量(即a.shape[axis]`)相匹配。
3.2 repeats 为数组或列表
当 repeats 是一个数组或列表时,它指定了输入数组中每个对应的元素或切片应该重复的次数。
-
一维数组:
repeats的长度必须与输入数组的长度相同。“`python
arr1d_complex = np.array([1, 2, 3])1 重复 1 次,2 重复 3 次,3 重复 2 次
result5 = np.repeat(arr1d_complex, [1, 3, 2])
print(“\nResult 5 (variable repeats for 1D):”, result5)Output: [1 2 2 2 3 3]
“`
-
多维数组 (
axis指定):repeats序列的长度必须与axis指定的维度的大小相同。“`python
arr2d_complex = np.array([[1, 2], [3, 4]])沿 axis=0 (行) 重复:第一行重复 1 次,第二行重复 3 次
result6 = np.repeat(arr2d_complex, [1, 3], axis=0)
print(“\nResult 6 (variable repeats for rows):”)
print(result6)Output:
[[1 2]
[3 4]
[3 4]
[3 4]]
沿 axis=1 (列) 重复:第一列重复 2 次,第二列重复 1 次
result7 = np.repeat(arr2d_complex, [2, 1], axis=1)
print(“\nResult 7 (variable repeats for columns):”)
print(result7)Output:
[[1 1 2]
[3 3 4]]
“`
4. 高级应用场景
np.repeat 在许多数据处理任务中都非常有用,尤其是在需要扩展数据维度、对数据进行插值或为某些算法准备输入时。
4.1 数据增强/上采样
在机器学习中,有时需要对数据进行简单的增强,或者在某些维度上进行上采样。repeat 可以方便地实现这一点。
“`python
假设有一组特征数据,需要将每个样本重复几次
data = np.array([[10, 20], [30, 40]]) # 2个样本,每个2个特征
每个样本(行)重复 2 次
augmented_data = np.repeat(data, 2, axis=0)
print(“\nAugmented Data (each sample repeated):”)
print(augmented_data)
Output:
[[10 20]
[10 20]
[30 40]
[30 40]]
“`
4.2 准备广播操作
在进行广播(Broadcasting)操作时,如果一个数组的维度需要扩展以匹配另一个数组的形状,repeat 可以作为一个有用的工具,尽管有时 np.newaxis 或 reshape 也能达到类似目的。
例如,有一个 1xN 的数组,需要将其重复 M 次以与 MxN 数组进行元素级运算。
“`python
row_vector = np.array([1, 2, 3])
将行向量重复 4 次,形成一个 4×3 的矩阵
matrix = np.repeat(row_vector[np.newaxis, :], 4, axis=0)
print(“\nMatrix created for broadcasting:”)
print(matrix)
Output:
[[1 2 3]
[1 2 3]
[1 2 3]
[1 2 3]]
``row_vector[np.newaxis, :]
这里将一维数组转换为二维行向量[[1, 2, 3]],然后repeat沿着axis=0` 重复这个行向量。
4.3 创建网格或棋盘图案
通过结合 repeat 和其他 NumPy 操作,可以有效地创建复杂的图案或网格。
“`python
创建一个简单的 2×2 模式
pattern = np.array([[0, 1], [1, 0]])
在行和列方向上重复,创建更大的棋盘
checkerboard = np.repeat(np.repeat(pattern, 2, axis=0), 2, axis=1)
print(“\nCheckerboard pattern:”)
print(checkerboard)
Output:
[[0 0 1 1]
[0 0 1 1]
[1 1 0 0]
[1 1 0 0]]
“`
5. np.repeat 与 np.tile 的区别
repeat 和 tile 都是用来扩展数组的函数,但它们的机制截然不同。这是 NumPy 初学者常混淆的地方。
-
np.repeat(a, repeats, axis=None): 重复数组中的每个元素或切片。- 当
axis=None时,它会展平数组a,然后对每个标量元素进行重复。 - 当
axis指定时,它会沿着该轴复制“完整”的元素或子数组。
- 当
-
np.tile(a, reps): 重复整个数组a本身,或重复数组a的“瓦片”(tile)。reps可以是一个整数或一个元组。- 如果
reps是一个整数,则将a作为整体在第一个维度上重复reps次。 - 如果
reps是一个元组,例如(m, n),则将a在行方向上重复m次,在列方向上重复n次,形成一个更大的“瓦片网格”。
让我们通过一个例子来比较:
“`python
arr = np.array([1, 2])
使用 repeat: 每个元素重复 3 次
repeat_result = np.repeat(arr, 3)
print(“\nrepeat([1, 2], 3):”, repeat_result)
Output: [1 1 1 2 2 2]
使用 tile: 整个数组 [1, 2] 作为整体重复 3 次
tile_result = np.tile(arr, 3)
print(“tile([1, 2], 3):”, tile_result)
Output: [1 2 1 2 1 2]
arr2d_comp = np.array([[1, 2], [3, 4]])
repeat(arr2d_comp, 2, axis=0) – 每行重复2次
repeat_2d_axis0 = np.repeat(arr2d_comp, 2, axis=0)
print(“\nrepeat([[1,2],[3,4]], 2, axis=0):\n”, repeat_2d_axis0)
Output:
[[1 2]
[1 2]
[3 4]
[3 4]]
tile(arr2d_comp, (2,1)) – 整个数组在行方向重复2次,列方向重复1次
tile_2d_reps = np.tile(arr2d_comp, (2, 1))
print(“tile([[1,2],[3,4]], (2,1)):\n”, tile_2d_reps)
Output:
[[1 2]
[3 4]
[1 2]
[3 4]]
“`
从上面的例子可以看出,repeat 倾向于“放大”现有元素,而 tile 倾向于“平铺”整个数组的副本。
6. 总结
numpy.repeat 是 NumPy 中一个强大且灵活的数组操作函数。通过其 repeats 和 axis 参数的组合,我们可以实现对数组元素进行各种方式的重复和扩展,无论是简单的元素复制,还是复杂的多维数据结构重塑。理解 repeat 与 tile 的核心区别,能帮助您在不同的数据处理场景中选择最合适的工具,从而更高效地操纵您的 NumPy 数组。