NumPy 数组创建的常见陷阱与高效替代方案
NumPy 数组创建的常见陷阱与高效替代方案
2025-12-12
NumPy 是 Python 中进行科学计算的基础库,其核心是 ndarray 对象,它允许我们高效地进行数组操作。
在创建 NumPy 数组时,我们通常使用 np.array() 或各种辅助函数(如 np.zeros(), np.ones(), np.arange() 等)。以下是一些常见的“陷阱”和更优雅的解决方案。
NumPy 数组要求所有元素必须是同一种数据类型(homogeneous)。如果您传入包含不同类型元素的列表,NumPy 会尝试将它们转换成一个“兼容”的类型,这可能会导致非预期的结果。
当数组中包含不同类型(例如,整数和字符串)时,NumPy 会将所有元素提升(upcast)为可以容纳所有数据的通用类型(通常是字符串)。
import numpy as np
# 包含数字和字符串的列表
data = [1, 2, '3', 4.0]
arr = np.array(data)
print(arr)
print(arr.dtype)
# 输出: ['1' '2' '3' '4.0']
# 输出: 此时,您将无法对这个数组进行正常的数值计算。 如果您确定需要的是数值类型,并且可以接受数据转换(例如,字符串'3'可以转换为数字3),您可以明确指定所需的数据类型。 # 明确指定数据类型为浮点数 arr_float = np.array(data, dtype=float) print(arr_float) print(arr_float.dtype) # 输出: [1. 2. 3. 4.] # 输出: float64 # 或者,如果只需要整数,但会丢失浮点数的精度 arr_int = np.array([1, 2, 3.5, 4], dtype=int) print(arr_int) # 输出: [1 2 3 4] (3.5被截断为3) np.array() 尝试创建多维数组时,要求其嵌套列表的“行”长度必须一致,否则它将创建一个元素为 Python 对象的一维数组,而不是预期的多维数组。 # 内部列表长度不一致 data_irregular = [[1, 2], [3, 4, 5]] arr_irregular = np.array(data_irregular) print(arr_irregular) print(arr_irregular.shape) # 输出: [list([1, 2]) list([3, 4, 5])] # 输出: (2,) (这是一个长度为2的一维数组,元素是Python列表) 这不是一个标准的 2xN 矩阵,无法进行矩阵运算。 如果您必须处理不规则数据,可以考虑使用 dtype=object 来明确创建一个包含 Python 对象的数组,或者在数据准备阶段进行填充(例如用 NaN 或 0 填充)使其规则化。 # 明确创建对象数组 arr_object = np.array(data_irregular, dtype=object) print(arr_object) print(arr_object.dtype) # 输出: [list([1, 2]) list([3, 4, 5])] # 输出: object # 更好的是,先将数据整理成规则形状 data_regular = [[1, 2, 0], [3, 4, 5]] # 填充一个0 arr_regular = np.array(data_regular) print(arr_regular) print(arr_regular.shape) # 输出: [[1 2 0] # [3 4 5]] # 输出: (2, 3) (这是一个 2x3 的二维数组) 对于大规模的数组,先创建一个预定形状和类型的数组,再填充数值,通常比从 Python 列表转换更高效。 # 使用 Python 列表初始化一个 1000x1000 的数组效率很低且代码繁琐 # large_arr = np.array([[0] * 1000] * 1000) NumPy 提供了专门的函数来创建填充特定值的数组 函数描述示例代码np.zeros()创建全为 0 的数组np.zeros((2, 3))np.ones()创建全为 1 的数组np.ones((2, 3))np.empty()创建一个未初始化(随机值)的数组,速度最快np.empty((2, 3))np.full()创建一个填充指定值的数组np.full((2, 3), 99.0)np.zeros_like() / np.ones_like()创建与另一个数组形状和类型相同的数组np.zeros_like(existing_arr)# 创建一个 3 行 4 列的全零浮点数组 zeros_arr = np.zeros((3, 4), dtype=float) print("np.zeros():\n", zeros_arr) # 创建一个 2 行 2 列的全99的整数数组 full_arr = np.full((2, 2), 99, dtype=int) print("np.full():\n", full_arr) 创建等差数列(如范围内的数字)时,避免使用 Python 内置的 range() 再转为 NumPy 数组。 # 不推荐:先创建列表再转换 arr = np.array(list(range(0, 10, 2))) 函数描述示例代码np.arange()类似于 Python 的 range(),基于步长创建数组np.arange(0, 10, 2) # 0, 2, 4, 6, 8np.linspace()基于元素数量创建等间隔的数组np.linspace(0, 10, 5) # 0, 2.5, 5.0, 7.5, 10.0# 使用 arange,从 10 到 19 range_arr = np.arange(10, 20) print("np.arange():", range_arr) # 使用 linspace,在 0 和 1 之间创建 5 个等间隔的数(包含终止点) lin_arr = np.linspace(0, 1, 5) print("np.linspace():", lin_arr) NumPy 数组创建的更多细节可以在 Solving 100 Python NumPy Problems! (From easy to difficult) 这个视频中找到。