NumPy:快速认识 ndarray 数组 在科学计算与数据分析领域计算效率与数据结构同样重要。NumPy 通过引入统一类型的多维数组将数据表示与批量运算结合起来使大规模数值计算成为可能。一、为什么需要数组计算在纯 Python 中我们通常使用 list 存储一组数据nums [1, 2, 3, 4]这种结构适合通用数据容器但并不适合大规模数值计算。原因在于• 列表中的元素是对象引用而不是连续数值块• 每个元素可以是不同类型• 运算依赖 Python 解释器逐个循环执行比如result [x * 2 for x in nums] # Python 层循环在数值规模较大时这种执行会产生两个问题1内存布局分散缓存利用率低2运算在解释器层逐元素执行无法批量优化而科学计算的核心需求是• 同类型数值的紧凑存储• 对规则内存布局的高效访问• 批量执行能力• 向量化计算支持NumPy 的 ndarray 正是在这一背景下被设计出来的。二、ndarray 的结构构成在 NumPy 中几乎所有数值计算都围绕一个核心类型展开numpy.ndarray它是“n-dimensional array”的缩写即“n 维数组”。ndarray 是一个类class其对象实例表示一个 n 维数组。每一个 ndarray 实例都包含以下关键结构信息1底层数据缓冲区2数据类型描述dtype 属性3形状信息shape 属性4维度数量ndim 属性5元素总数size 属性6步长信息strides 属性延伸阅读《NumPy数组属性》这些属性共同决定这块连续内存如何被解释为一个多维数值结构。ndarray 以底层数据缓冲区Buffer和一组描述该数据如何解释的元数据metadata构成。很多数组是连续存储的但数组视图不一定总是内存连续。延伸阅读《NumPy数组复制与视图》三、dtype数组元素的类型在 Python 列表中lst [1, 2.5, abc]元素类型可以完全不同。而在 ndarray 中import numpy as nparr np.array([1, 2, 3]) # 返回 ndarray 对象ndarray 中的元素会以统一的 dtype 存储和解释。NumPy 会强制转换为同一 dtype并不是要求输入同一类型。dtype 是 ndarray 对象的一个属性用于描述数组中每个元素的数据类型。查看类型print(arr.dtype) print(arr.itemsize) # 每个元素占用字节数在多数 64 位系统上输出int648表示 arr 数组中的每个元素是一个占 8 字节的整数。常见的 dtype 数据类型有• 整数int32 / int64• 浮点数float32 / float64• 布尔型bool• 复数complex128可以在创建数组时手动指定元素的类型arr np.array([1, 2, 3], dtypenp.float32)print(arr.dtype) # float32print(arr.itemsize) # 每个元素占用字节数NumPy 还会根据输入推断一个“可兼容”的统一类型arr np.array([1, 2.5]) print(arr.dtype) # float64统一元素数据类型具有以下意义• 决定每个元素占用的字节数影响内存• 决定数值精度影响计算结果• 决定运算行为整数运算或浮点运算等dtype 是 ndarray 的类型系统基础。延伸阅读《NumPydtype 数据类型》四、shape数组的结构信息shape 是 ndarray 的属性返回一个元组表示数组在每个维度上的长度。示例arr np.array([[1, 2, 3], [4, 5, 6]]) print(arr.shape) # (2, 3)表示数组第 0 维的长度为 2第 1 维的长度为 3这是一个 2 行 3 列的二维数组。ndarray 数组还提供了其他属性来查看相关结构信息.ndim数组的维度数量.size数组的元素总数print(arr.ndim) # 2 表示这是个二维数组print(arr.size) # 6 表示元素总数 2*3NumPy 使用统一的 ndarray 结构描述任意维度的数据。从数学对象的角度看不同维度的 ndarray 通常可以这样理解• 0 维 ndarray可看作标量Scalar的数组化表示• 1 维 ndarray通常可表示向量Vector• 2 维 ndarray通常可表示矩阵Matrix• 3 维及以上 ndarray通常可表示更高阶张量Tensor五、创建 ndarray 的方法与 Python 的 list 不同ndarray 没有专属字面量语法如 {} 或 []。它必须通过 NumPy 提供的函数构造。这些函数都可以指定 dtype并返回 ndarray 对象。若未指定 dtypeNumPy 会根据输入数据自动推断某些初始化函数如 zeros、ones默认 dtype 为 float64。1、从序列创建np.array() 主要用于将序列列表、元组及嵌套序列等转换为 ndarray。np.array(object, dtypeNone)示例arr np.array([1, 2, 3]) # 返回 ndarray提示由于集合set不能保证顺序、字典dict只会取键因此不建议使用它们来转换为 ndarray。2、区间创建np.arange()生成等间隔数值序列返回 ndarray。np.arange(start, stop, step, dtypeNone)示例arr np.arange(0, 10, 2) # [0 2 4 6 8]np.linspace() 可按给定区间和数量生成等距数值返回 ndarray。np.linspace(start, stop, num, dtypeNone)示例arr np.linspace(1, 9, 5) # 默认 float64说明np.linspace() 默认结果通常为浮点类型。3、初始化函数np.zeros() 可返回元素全是 0 的 ndarray 数组。np.zeros(shape, dtypeNone)示例arr np.zeros((2, 3))np.ones() 可返回元素全是 1 的 ndarray 数组。np.ones(shape, dtypeNone)示例arr np.ones((2, 2, 3)) # 返回一个三维数组np.full() 可返回元素全是指定值的 ndarray 数组。np.full(shape, fill_value, dtypeNone)示例arr np.full((2, 3), 5) # 返回全是 5 的两行三列的二维数组np.eye() 默认可创建主对角线为 1、其余为 0 的二维数组最常见情形是单位矩阵。np.eye(N, MNone, k0, dtypefloat)示例arr np.eye(5) # 返回一个 5 行 5 列的单位矩阵从结构层面看这些函数都会分配一块连续内存缓冲区并为其附加 dtype、shape 等元数据最终构造一个 ndarray 实例。要注意的是当直接打印创建好的 ndarray 实例print(arr)输出形式通常为[[1 2] [3 4]]这是“字符串表示”不是语法结构。特点• 元素之间以空格分隔不是逗号• 多维结构使用嵌套方括号表示延伸阅读《NumPy 函数手册数组创建》六、基础索引与切片虽然 ndarray 没有字面量语法但它支持与列表类似的索引和切片语法。1、索引1一维索引使用 [ ] 选取单个位置通常返回一个标量值。arr np.array([10, 20, 30])arr[0]2多维索引使用逗号分隔维度。arr np.array([[1, 2], [3, 4]]) arr[0, 1]虽然 arr[0][1] 也是合法表达式但它会先返回一个中间数组对象再进行索引。推荐使用 arr[0, 1] 这种多维索引元组形式。2、切片在 ndarray 中切片语法沿用 Python 的基本切片表达式形式start : stop : step对于一维数组而言切片方式几乎是一样arr np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])arr[::2] # [0 2 4 6 8]不过NumPy 支持“多维同时切片”并且每个维度的切片表达式使用逗号分隔。一般形式为arr[维度0切片, 维度1切片, ..., 维度N切片]此处的“维度n切片”可以是• 整数选取该维度的某个位置• 切片表达式start:stop:step• 冒号 :表示该维度全部• 省略号 ...表示剩余所有维度示例import numpy as np arr np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])对于二维数组而言维度切片表达式 arr[a, b] 中第 0 个位置对应第 0 维通常理解为“行”第 1 个位置对应第 1 维通常理解为“列”。但从机制上看NumPy 并不是“先选行再选列”而是同时对两个维度进行索引。比如选取第 0 列col arr[:, 0] # [1 4 7]第 0 维使用 : 表示选取所有行。第 1 维使用 0 表示选取第 0 列。选取前两行、后两列sub arr[0:2, 1:3]0:2 表示选取第 0 行、第 1 行。1:3 表示选取第 1 列、第 2 列。要强调的是在多数基本切片情况下不包含高级索引返回的是原数组的“视图”通常共享内存。延伸阅读《NumPy数组元素访问》七、数组运算的统一模型NumPy 数组支持逐元素运算。a np.array([1, 2, 3])b np.array([4, 5, 6]) a b结果[5 7 9]运算由底层 C 实现的 ufunc通用函数执行在连续内存上进行逐元素批量计算。这种逐元素批量计算模式通常称为向量化vectorization是 NumPy 获得高性能的重要原因之一。延伸阅读《NumPy 函数手册数值运算》《NumPy 函数手册聚合与统计》 小结ndarray 是由底层数据缓冲区与结构元数据共同构成的多维数值数组对象。其 dtype、shape、strides 等属性用于解释内存布局实现统一类型与向量化计算。这种结构突破了 Python 列表的对象模型限制是科学计算与机器学习的基础数据结构。“点赞有美意赞赏是鼓励”