使用NumPy reshape进行数据重塑 – wiki大全

NumPy 是 Python 中用于科学计算的核心库,提供了高性能的多维数组对象(ndarray)和用于处理这些数组的工具。在数据分析和机器学习领域,数据的形状(shape)经常需要调整以适应不同的算法或分析需求。NumPy 的 reshape 函数就是实现这一目标的关键工具之一。

使用 NumPy reshape 进行数据重塑

reshape 函数允许你更改数组的维度,同时保持其数据不变。这对于将一维数据转换成多维矩阵、将多维数据展平、或者调整数据的排列以匹配特定算法的输入格式至关重要。

1. reshape 的基本用法

reshape 函数可以通过两种主要方式调用:
1. 作为 ndarray 对象的方法:arr.reshape(new_shape)
2. 作为 NumPy 模块的函数:numpy.reshape(arr, new_shape)

在这两种情况下,new_shape 参数是一个整数元组,指定了数组的新维度。

核心原则: 重塑后的数组的元素总数必须与原始数组的元素总数相同。
np.prod(original_shape) == np.prod(new_shape)

示例:
“`python
import numpy as np

创建一个一维数组

arr_1d = np.arange(12) # [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(“原始一维数组:”, arr_1d)
print(“原始形状:”, arr_1d.shape)

将一维数组重塑为 3×4 的二维数组

arr_2d = arr_1d.reshape((3, 4))
print(“\n重塑为 3×4 数组:\n”, arr_2d)
print(“新形状:”, arr_2d.shape)

将一维数组重塑为 2x2x3 的三维数组

arr_3d = arr_1d.reshape((2, 2, 3))
print(“\n重塑为 2x2x3 数组:\n”, arr_3d)
print(“新形状:”, arr_3d.shape)

也可以将多维数组重塑回一维

arr_flat = arr_2d.reshape((12,)) # 或 arr_2d.reshape(-1)
print(“\n将 2D 数组重塑回 1D:\n”, arr_flat)
print(“新形状:”, arr_flat.shape)
“`

输出示例:
“`
原始一维数组: [ 0 1 2 3 4 5 6 7 8 9 10 11]
原始形状: (12,)

重塑为 3×4 数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
新形状: (3, 4)

重塑为 2x2x3 数组:
[[[ 0 1 2]
[ 3 4 5]]

[[ 6 7 8]
[ 9 10 11]]]
新形状: (2, 2, 3)

将 2D 数组重塑回 1D:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
新形状: (12,)
“`

2. 使用 -1 自动推断维度

new_shape 元组中,你可以使用 -1 来让 NumPy 自动计算该维度的大小。这在你不确定某个维度具体应该有多大,但知道其他维度时非常有用。但是,只能有一个维度被设置为 -1

示例:
“`python
arr = np.arange(15) # 15个元素

重塑为 3 行,列数自动推断

arr_3_rows = arr.reshape((3, -1))
print(“重塑为 3 行,列数自动推断:\n”, arr_3_rows)
print(“形状:”, arr_3_rows.shape) # (3, 5)

重塑为 5 列,行数自动推断

arr_5_cols = arr.reshape((-1, 5))
print(“\n重塑为 5 列,行数自动推断:\n”, arr_5_cols)
print(“形状:”, arr_5_cols.shape) # (3, 5)

重塑为多个维度,其中一个自动推断

arr_auto_3d = arr.reshape((3, -1, 5)) # (3, 1, 5)
print(“\n重塑为 3x(-1)x5 数组:\n”, arr_auto_3d)
print(“形状:”, arr_auto_3d.shape)
“`

输出示例:
“`
重塑为 3 行,列数自动推断:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
形状: (3, 5)

重塑为 5 列,行数自动推断:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
形状: (3, 5)

重塑为 3x(-1)x5 数组:
[[[ 0 1 2 3 4]]

[[ 5 6 7 8 9]]

[[10 11 12 13 14]]]
形状: (3, 1, 5)
“`

3. order 参数

reshape 函数有一个可选的 order 参数,它决定了在读取和写入元素时,数组数据是以哪种顺序进行解释的。这对于理解数据在内存中的存储方式以及重塑如何影响元素排列至关重要。

  • 'C' (默认): 以 C 语言风格的行主序(row-major)读取/写入元素。这意味着最右边的索引变化最快。
  • 'F' : 以 Fortran 语言风格的列主序(column-major)读取/写入元素。这意味着最左边的索引变化最快。
  • 'A' : 如果数组是 Fortran 连续的,则使用 Fortran 风格,否则使用 C 风格。
  • 'K' : 保留元素在内存中出现的顺序。

示例:
“`python
arr = np.arange(6) # [0 1 2 3 4 5]

C 顺序 (默认)

arr_c = arr.reshape((2, 3), order=’C’)
print(“C 顺序重塑 (默认):\n”, arr_c)

F 顺序

arr_f = arr.reshape((2, 3), order=’F’)
print(“\nF 顺序重塑:\n”, arr_f)
“`

输出示例:
“`
C 顺序重塑 (默认):
[[0 1 2]
[3 4 5]]

F 顺序重塑:
[[0 3 4]
[1 2 5]]
``
可以看到,在
order=’F’的情况下,元素是按列填充的:首先是0, 1(第一列),然后是2, 3(第二列,但由于原始数组只有6个元素,这里实际是2之后跳到了3),接着是4, 5`。

4. reshape 返回视图还是副本?

通常,如果可能的话,reshape 会返回原始数组的一个视图(view)。这意味着重塑后的数组和原始数组共享底层数据缓冲区。对视图的修改会反映在原始数组上,反之亦然。
如果由于数据存储方式(例如,非连续内存块)或 order 参数的特殊要求,无法创建视图,则 reshape 会返回一个副本(copy)。

你可以通过 arr.base 属性来检查一个数组是否是另一个数组的视图。如果 arr.base 不是 None 且不等于 arr 本身,那么 arr 就是 arr.base 的一个视图。

示例:
“`python
arr = np.arange(6)
reshaped_arr = arr.reshape((2, 3))

print(“原始数组:”, arr)
print(“重塑后的数组:\n”, reshaped_arr)

检查是否为视图

print(“重塑后的数组的基对象 (base):”, reshaped_arr.base) # 应该是非 None

修改视图

reshaped_arr[0, 0] = 99
print(“\n修改视图后:”)
print(“原始数组:”, arr)
print(“重塑后的数组:\n”, reshaped_arr)
“`

输出示例:
“`
原始数组: [0 1 2 3 4 5]
重塑后的数组:
[[0 1 2]
[3 4 5]]
重塑后的数组的基对象 (base): [0 1 2 3 4 5]

修改视图后:
原始数组: [99 1 2 3 4 5]
重塑后的数组:
[[99 1 2]
[ 3 4 5]]
``
在这个例子中,
reshaped_arrarr的一个视图,修改reshaped_arr会直接影响arr`。

5. 与 flatten()ravel() 的比较

当你想将多维数组展平为一维数组时,flatten()ravel() 是常用的方法:

  • flatten(): 总是返回原始数组的一个副本。它有一个 order 参数,可以指定展平的顺序。
  • ravel(): 通常返回原始数组的一个视图,如果原始数组在内存中是连续的。只有在原始数组不连续时,才会返回副本。它也有一个 order 参数。
  • reshape(-1): 这是一种特殊的 reshape 用法,它将数组展平为一维。与 ravel() 类似,它会尽可能返回视图,并在必要时返回副本。

在性能敏感的应用中,优先考虑 ravel()reshape(-1),因为它们通常可以避免数据复制。如果需要保证独立副本,则使用 flatten()

总结

NumPy 的 reshape 函数是数据处理中不可或缺的工具,它提供了灵活的方式来调整多维数组的形状。理解其基本用法、-1 自动推断维度、order 参数以及视图/副本行为,将使你能够有效地操纵数据结构,为后续的分析和模型训练做好准备。掌握 reshape 不仅能提高代码效率,还能帮助你更好地理解和控制数据在内存中的布局。

滚动至顶部