为了在数值计算中有效使用 NumPy 数组,了解它们的结构并知道如何修改它至关重要。每个 NumPy 数组都带有内置的特性,称为属性,它们描述了数组的特点。了解这些属性对于调试、理解内存使用以及为机器学习算法准备数据都很有用。这还涵盖了如何在不改变数组底层数据的情况下改变其形状,这是数据处理中的一个常见要求。理解数组属性NumPy 数组有一些有用的属性,可以提供关于数组本身的信息。这些属性使用点表示法访问(例如,my_array.attribute_name)。以下是一些最常用的属性:ndarray.ndim:此属性指示数组的维度数量(或轴数)。向量(例如 [1, 2, 3])有 1 个维度,而矩阵(例如 [[1, 2], [3, 4]])有 2 个维度。ndarray.shape:这提供了一个元组,指示数组在每个维度上的大小。对于一个包含 3 个元素的一维数组,shape 将是 (3,)。对于一个包含 2 行 4 列的二维数组(矩阵),shape 将是 (2, 4)。ndarray.size:这表示数组中元素的总数。它就是 shape 元组中数字的乘积。对于形状为 (2, 4) 的数组,size 为 $2 \times 4 = 8$。ndarray.dtype:这指定了数组中存储元素的数据类型。常见类型包括 int64(64 位整数)、float64(64 位浮点数)和 bool(布尔值)。数据类型会影响数组使用的内存量和计算的精度。让我们看看这些属性如何使用。import numpy as np # 创建一个一维数组(向量) vec = np.array([10, 20, 30, 40]) # 创建一个二维数组(矩阵) mat = np.array([[1.5, 2.5, 3.5], [4.5, 5.5, 6.5]]) print("向量:") print(f" 数据: {vec}") print(f" 维度数量 (ndim): {vec.ndim}") print(f" 形状: {vec.shape}") print(f" 元素总数 (size): {vec.size}") print(f" 数据类型 (dtype): {vec.dtype}") print("\n矩阵:") print(f" 数据:\n{mat}") print(f" 维度数量 (ndim): {mat.ndim}") print(f" 形状: {mat.shape}") print(f" 元素总数 (size): {mat.size}") print(f" 数据类型 (dtype): {mat.dtype}")输出:向量: 数据: [10 20 30 40] 维度数量 (ndim): 1 形状: (4,) 元素总数 (size): 4 数据类型 (dtype): int64 矩阵: 数据: [[1.5 2.5 3.5] [4.5 5.5 6.5]] 维度数量 (ndim): 2 形状: (2, 3) 元素总数 (size): 6 数据类型 (dtype): float64请注意,一维数组 vec 的 shape 是 (4,),表示一个长度为 4 的维度。二维数组 mat 的 shape 是 (2, 3),表示 2 个维度(行和列),长度分别为 2 和 3。size 是元素的总数,dtype 反映了创建时使用的数字类型(vec 为 int,mat 为 float)。改变数组形状通常,你的数据可能是一种形状,但需要将其转换为另一种形状。例如,你可能有一个来自图像的像素值长列表(一维),你希望将其排列成代表图像高度和宽度的网格(二维)。NumPy 提供了函数来调整数组形状而不改变其数据内容。实现此目的主要方法是 reshape() 函数。ndarray.reshape(new_shape)此方法返回一个新数组,其数据与原始数组相同,但按 new_shape 排列。重要规则是元素总数 (size) 必须保持不变。你不能将一个大小为 6 的数组调整为需要 7 个元素的形状。# 创建一个包含 12 个元素的一维数组 data = np.arange(12) # 创建数组 [0, 1, ..., 11] print(f"原始数组(形状 {data.shape}):\n{data}") # 调整为 3x4 矩阵 matrix_3x4 = data.reshape((3, 4)) print(f"\n调整为 3x4(形状 {matrix_3x4.shape}):\n{matrix_3x4}") # 调整为 4x3 矩阵 matrix_4x3 = data.reshape((4, 3)) print(f"\n调整为 4x3(形状 {matrix_4x3.shape}):\n{matrix_4x3}") # 调整为 2x6 矩阵 matrix_2x6 = data.reshape((2, 6)) print(f"\n调整为 2x6(形状 {matrix_2x6.shape}):\n{matrix_2x6}") # 尝试进行无效的形状调整 try: invalid_shape = data.reshape((3, 5)) # 3 * 5 = 15,原始大小为 12 except ValueError as e: print(f"\n调整为 (3, 5) 时出错:{e}")输出:原始数组(形状 (12,)): [ 0 1 2 3 4 5 6 7 8 9 10 11] 调整为 3x4(形状 (3, 4)): [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] 调整为 4x3(形状 (4, 3)): [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]] 调整为 2x6(形状 (2, 6)): [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11]] 调整为 (3, 5) 时出错:cannot reshape array of size 12 into shape (3,5)请注意,元素是如何按行填充新形状的。尝试将形状调整为 (3, 5) 失败,因为 $3 \times 5 = 15$,这与原始的 size 12 不匹配。使用 -1 推断维度有时,你只知道除一个维度外的所有维度的大小。你可以在 reshape 元组中使用 -1 作为占位符,NumPy 会根据元素总数自动计算该维度的正确大小。data = np.arange(12) # 数组 [0, 1, ..., 11] # 调整为 2 行,自动计算列数 matrix_2_rows = data.reshape((2, -1)) print(f"调整为 (2, -1) -> 形状 {matrix_2_rows.shape}:\n{matrix_2_rows}") # 调整为 4 列,自动计算行数 matrix_4_cols = data.reshape((-1, 4)) print(f"\n调整为 (-1, 4) -> 形状 {matrix_4_cols.shape}:\n{matrix_4_cols}")输出:调整为 (2, -1) -> 形状 (2, 6): [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11]] 调整为 (-1, 4) -> 形状 (3, 4): [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]在第一个例子中,NumPy 计算出要在 2 行中容纳 12 个元素,它需要 $12 / 2 = 6$ 列。在第二个例子中,它计算出 $12 / 4 = 3$ 行。这种使用 -1 的方法非常方便。digraph G { rankdir=LR; node [shape=box, style=filled, fillcolor="#e9ecef"]; splines=false; "一维数组(12 个元素)" -> "reshape((3, 4))" -> "二维数组 (3x4)"; "一维数组(12 个元素)" [label="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]\n形状: (12,)\n大小: 12"]; "二维数组 (3x4)" [label="[[ 0, 1, 2, 3],\n [ 4, 5, 6, 7],\n [ 8, 9, 10, 11]]\n形状: (3, 4)\n大小: 12"]; "reshape((3, 4))" [shape=ellipse, style=dashed, fillcolor="#a5d8ff"]; }这是将一个包含 12 个元素的一维数组使用 reshape((3, 4)) 调整为 3 行 4 列的二维数组的示意图。元素的总数仍为 12。展平数组将多维数组调整为一维数组的逆向操作称为展平:即将多维数组转换为一维数组。ravel() 方法常用于此目的。ndarray.ravel()此方法返回一个展平的一维数组,其中包含原始数组的所有元素。如果可能,它通常返回原始数组的视图,这意味着它不会在内存中创建数据的副本,从而非常高效。matrix = np.array([[1, 2, 3], [4, 5, 6]]) print(f"原始矩阵(形状 {matrix.shape}):\n{matrix}") # 展平矩阵 flattened_array = matrix.ravel() print(f"\n展平数组(形状 {flattened_array.shape}):\n{flattened_array}")输出:原始矩阵(形状 (2, 3)): [[1 2 3] [4 5 6]] 展平数组(形状 (6,)): [1 2 3 4 5 6]ravel() 方法按行读取元素以创建一维数组。了解 shape、size 和 dtype 等数组属性,以及掌握如何使用 reshape 和 ravel 调整 shape,是高效使用 NumPy 的基本能力。这些操作在为机器学习模型准备输入数据或解析线性代数计算结果时经常用到。