神铸利刃·装备养成活动门户

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) 这个视频中找到。