当前位置: 首页 > news >正文

CQF预备知识:Python相关库 -- NumPy 基础知识 - 数组创建

文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。

数组创建

另请参阅 数组创建例程

引言

创建数组有6种通用机制:

  1. 从其他Python结构转换(即列表和元组)。

  2. 使用NumPy内置的数组创建函数(例如arangeoneszeros等)。

  3. 复制、连接或修改现有数组。

  4. 从磁盘读取数组,无论是标准格式还是自定义格式。

  5. 通过使用字符串或缓冲区从原始字节创建数组。

  6. 使用特殊库函数(例如random)。

您可以使用这些方法创建ndarray或结构化数组。本文将涵盖ndarray创建的一般方法。

1)将 Python 序列转换为 NumPy 数组

可以使用 Python 序列(如列表和元组)来定义 NumPy 数组。列表和元组分别使用[...](...)定义。列表和元组可用于定义ndarray的创建:

  • 数字列表将创建一维数组。

  • 列表的列表将创建二维数组。

  • 更多嵌套列表将创建更高维度的数组。一般来说,NumPy 中的任何数组对象都被称为ndarray

>>> import numpy as np
>>> a1D = np.array([1, 2, 3, 4])
>>> a2D = np.array([[1, 2], [3, 4]])
>>> a3D = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

当您使用numpy.array定义新数组时,您应该考虑数组中元素的dtype,可以明确指定dtype。此功能使您能够更好地控制底层数据结构以及在 C/C++ 函数中处理元素的方式。如果值超出范围且您使用了dtype,NumPy 可能会引发错误:

>>> import numpy as np
>>> np.array([127, 128, 129], dtype=np.int8)
Traceback (most recent call last):
...
OverflowError: Python integer 128 out of bounds for int8

8 位有符号整数表示从 -128 到 127 的整数。将int8数组分配给此范围之外的整数会导致溢出。此功能常常被误解。如果您使用不匹配的dtype进行计算,可能会得到意外的结果,例如:

>>> import numpy as np
>>> a = np.array([2, 3, 4], dtype=np.uint32)
>>> b = np.array([5, 6, 7], dtype=np.uint32)
>>> c_unsigned32 = a - b
>>> print('unsigned c:', c_unsigned32, c_unsigned32.dtype)
unsigned c: [4294967293 4294967293 4294967293] uint32
>>> c_signed32 = a - b.astype(np.int32)
>>> print('signed c:', c_signed32, c_signed32.dtype)
signed c: [-3 -3 -3] int64

注意,当您使用相同dtype的两个数组进行运算时:uint32,结果数组也是相同类型。当您使用不同dtype进行运算时,NumPy 将分配一个新类型,以满足计算中涉及的所有数组元素,在这里uint32int32都可以表示为int64

NumPy 的默认行为是创建 32 位或 64 位有符号整数数组(取决于平台并匹配 C 中long的大小)或双精度浮点数。如果您希望整数数组是特定类型,则需要在创建数组时指定dtype

2)NumPy 内置数组创建函数

NumPy 拥有超过40个内置函数用于创建数组,这些函数在数组创建例程中有详细说明。这些函数可以根据它们创建的数组维度大致分为三个类别:

  1. 一维数组

  2. 二维数组

  3. 多维数组(ndarray

一维数组创建函数

例如numpy.linspacenumpy.arange这样的创建一维数组的函数通常至少需要两个输入参数:start(起始值)和stop(结束值)。

numpy.arange用于创建具有规律性递增值的数组。更多详细信息和示例,请查阅文档。以下是一些示例:

>>> import numpy as np
>>> np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(2, 10, dtype=float)
array([2., 3., 4., 5., 6., 7., 8., 9.])
>>> np.arange(2, 3, 0.1)
array([2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9])

注意:使用numpy.arange的最佳实践是使用整数作为起始值、结束值和步长。关于dtype有一些需要注意的地方。在第二个示例中,定义了dtype。在第三个示例中,数组的dtypefloat,以适应步长0.1。由于舍入误差,有时会包含stop值。

numpy.linspace将创建具有指定数量元素的数组,并且这些元素在指定的起始值和结束值之间等间距分布。例如:

>>> import numpy as np
>>> np.linspace(1., 4., 6)
array([1. ,  1.6,  2.2,  2.8,  3.4,  4. ])

这个创建函数的优势在于,您可以保证元素的数量以及起始值和结束值。而之前的arange(start, stop, step)则不会包含stop值。

二维数组创建函数

例如numpy.eyenumpy.diagnumpy.vander这样的二维数组创建函数定义了特殊矩阵的属性,这些矩阵以二维数组的形式表示。

np.eye(n, m)定义了一个二维单位矩阵。其中行索引和列索引相等(i=j)的元素为1,其余元素为0,如下所示:

>>> import numpy as np
>>> np.eye(3)
array([[1., 0., 0.],[0., 1., 0.],[0., 0., 1.]])
>>> np.eye(3, 5)
array([[1., 0., 0., 0., 0.],[0., 1., 0., 0., 0.],[0., 0., 1., 0., 0.]])

numpy.diag可以根据给定的对角线值定义一个方阵,或者如果给定一个二维数组,则返回一个一维数组,该数组仅包含对角线元素。这两个数组创建函数在线性代数中非常有用,如下所示:

>>> import numpy as np
>>> np.diag([1, 2, 3])
array([[1, 0, 0],[0, 2, 0],[0, 0, 3]])
>>> np.diag([1, 2, 3], 1)
array([[0, 1, 0, 0],[0, 0, 2, 0],[0, 0, 0, 3],[0, 0, 0, 0]])
>>> a = np.array([[1, 2], [3, 4]])
>>> np.diag(a)
array([1, 4])

vander(x, n)定义了一个范德蒙矩阵,作为二维 NumPy 数组。范德蒙矩阵的每一列都是输入一维数组或元组x的递减幂次,其中最高多项式阶数为n-1。这个数组创建例程有助于生成线性最小二乘模型,如下所示:

>>> import numpy as np
>>> np.vander(np.linspace(0, 2, 5), 2)
array([[0. , 1. ],[0.5, 1. ],[1. , 1. ],[1.5, 1. ],[2. , 1. ]])
>>> np.vander([1, 2, 3, 4], 2)
array([[1, 1],[2, 1],[3, 1],[4, 1]])
>>> np.vander((1, 2, 3, 4), 4)
array([[ 1,  1,  1,  1],[ 8,  4,  2,  1],[27,  9,  3,  1],[64, 16,  4,  1]])

通用ndarray创建函数

例如numpy.onesnumpy.zerosrandom这样的ndarray创建函数可以根据所需的形状定义数组。通过在元组或列表中指定维度数量和每个维度的长度,这些ndarray创建函数可以创建任意维度的数组。

numpy.zeros将创建一个指定形状的数组,其中填充了0值。默认的dtypefloat64

>>> import numpy as np
>>> np.zeros((2, 3))
array([[0., 0., 0.],[0., 0., 0.]])
>>> np.zeros((2, 3, 2))
array([[[0., 0.],[0., 0.],[0., 0.]],[[0., 0.],[0., 0.],[0., 0.]]])

numpy.ones将创建一个填充了1值的数组。它在所有其他方面都与zeros相同,如下所示:

>>> import numpy as np
>>> np.ones((2, 3))
array([[1., 1., 1.],[1., 1., 1.]])
>>> np.ones((2, 3, 2))
array([[[1., 1.],[1., 1.],[1., 1.]],[[1., 1.],[1., 1.],[1., 1.]]])

random方法(来自default_rng的结果)将创建一个填充了介于0和1之间的随机值的数组。它包含在numpy.random库中。下面分别创建了形状为(2,3)(2,3,2)的两个数组。设置种子为42,以便您可以重现这些伪随机数:

>>> import numpy as np
>>> from numpy.random import default_rng
>>> default_rng(42).random((2,3))
array([[0.77395605, 0.43887844, 0.85859792],[0.69736803, 0.09417735, 0.97562235]])
>>> default_rng(42).random((2,3,2))
array([[[0.77395605, 0.43887844],[0.85859792, 0.69736803],[0.09417735, 0.97562235]],[[0.7611397 , 0.78606431],[0.12811363, 0.45038594],[0.37079802, 0.92676499]]])

numpy.indices将创建一组数组(作为一个更高维度的数组堆叠在一起),每个维度一个,每个数组代表该维度的变化:

>>> import numpy as np
>>> np.indices((3,3))
array([[[0, 0, 0],[1, 1, 1],[2, 2, 2]],[[0, 1, 2],[0, 1, 2],[0, 1, 2]]])

这在评估多维函数的规则网格上特别有用。

3)复制、连接或修改现有数组

一旦创建了数组,您可以通过复制、连接或修改现有数组来创建新数组。当您将数组或其元素赋值给一个新变量时,您需要显式地使用numpy.copy来复制数组,否则该变量只是原始数组的一个“视图”。考虑以下示例:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6])
>>> b = a[:2]
>>> b += 1
>>> print('a =', a, '; b =', b)
a = [2 3 3 4 5 6] ; b = [2 3]

在这个示例中,您并没有创建一个新数组。您创建了一个变量b,它只是查看了a的前两个元素。当您给b加1时,您会得到与给a[:2]加1相同的结果。如果您想创建一个新的数组,请使用numpy.copy数组创建例程,如下所示:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4])
>>> b = a[:2].copy()
>>> b += 1
>>> print('a = ', a, 'b = ', b)
a =  [1 2 3 4] b =  [2 3]

有关更多信息和示例,请查看副本和视图。

有许多例程可以连接现有数组,例如numpy.vstacknumpy.hstacknumpy.block。以下是一个使用block将四个2×2的数组连接成一个4×4的数组的示例:

>>> import numpy as np
>>> A = np.ones((2, 2))
>>> B = np.eye(2, 2)
>>> C = np.zeros((2, 2))
>>> D = np.diag((-3, -4))
>>> np.block([[A, B], [C, D]])
array([[ 1.,  1.,  1.,  0.],[ 1.,  1.,  0.,  1.],[ 0.,  0., -3.,  0.],[ 0.,  0.,  0., -4.]])

其他例程使用类似的语法来连接ndarray。请查看相关例程的文档以获取更多示例和语法。

4)从磁盘读取数组,无论是标准格式还是自定义格式

这是创建大型数组的最常见情况。细节在很大程度上取决于磁盘上数据的格式。本节提供有关如何处理各种格式的一般指导。有关更详细的输入/输出示例,请查看如何读取和写入文件。

标准二进制格式

各个领域都有数组数据的标准格式。以下列出了已知的 Python 库,这些库可以读取这些格式并返回 NumPy 数组(可能还有其他格式,可以通过读取并转换为 NumPy 数组,因此请查看最后一节内容)。

例如,一些格式不能直接读取,但很容易转换,这些格式由像 PIL(能够读取和写入许多图像格式,如 jpg、png 等)这样的库支持。

常见的 ASCII 格式

以逗号分隔值(csv)和制表符分隔值(tsv)文件为代表的分隔符文件,用于像 Excel 和 LabView 这样的程序。Python 函数可以逐行读取和解析这些文件。NumPy 有两个标准例程用于导入带有分隔符数据的文件,分别是numpy.loadtxtnumpy.genfromtxt。这些函数在读取和写入文件中有更复杂的用例。假设有一个名为simple.csv的文件,内容如下:

$ cat simple.csv
x, y
0, 0
1, 1
2, 4
3, 9

使用numpy.loadtxt导入simple.csv文件:

>>> import numpy as np
>>> np.loadtxt('simple.csv', delimiter = ',', skiprows = 1)
array([[0., 0.],[1., 1.],[2., 4.],[3., 9.]])

更通用的 ASCII 文件可以使用scipy.io和 Pandas 来读取。

5)通过使用字符串或缓冲区从原始字节创建数组

有多种方法可以使用。如果文件格式相对简单,那么可以编写一个简单的 I/O 库,并使用 NumPy 的fromfile()函数和.tofile()方法直接读取和写入 NumPy 数组(注意字节顺序!)。如果存在一个良好的 C 或 C++ 库可以读取数据,那么可以使用各种技术来包装该库,但这当然要多做很多工作,并且需要更高级的知识来与 C 或 C++ 进行接口。

6)使用特殊库函数(例如 SciPy、pandas 和 OpenCV)

NumPy 是 Python 科学计算堆栈中数组容器的基础库。许多 Python 库,包括 SciPy、Pandas 和 OpenCV,都使用 NumPy 的ndarray作为数据交换的通用格式。这些库可以创建、操作和处理 NumPy 数组。

风险提示与免责声明
本文内容基于公开信息研究整理,不构成任何形式的投资建议。历史表现不应作为未来收益保证,市场存在不可预见的波动风险。投资者需结合自身财务状况及风险承受能力独立决策,并自行承担交易结果。作者及发布方不对任何依据本文操作导致的损失承担法律责任。市场有风险,投资须谨慎。

相关文章:

  • Ubuntu20.04 gr-gsm完整安装教程
  • SQL每日一题
  • SQL SERVER常用聚合函数整理及示例
  • 全面指南:使用Node.js和Python连接与操作MongoDB
  • 二十五、面向对象底层逻辑-SpringMVC九大组件之HandlerMapping接口设计
  • 【Linux】进程基本概念与基本操作
  • 【深度学习新浪潮】如何用Dify构建自己的AI Agent?
  • 利用 XML 外部实体注入(XXE)读取文件和探测内部网络
  • 快速排序算法的C++和C语言对比
  • WordPress多语言插件安装与使用教程
  • Java核心基础
  • VMware Flings又又又搬家了
  • SAP全面转向AI战略,S/4HANA悄然隐身
  • 【每日一题】【前缀和优化】【前/后缀最值】牛客练习赛139 B/C题 大卫的密码 (Hard Version) C++
  • 基于netmiko模块实现支持SSH or Telnet的多线程多厂商网络设备自动化巡检脚本
  • 教育信息化2.0时代下学校网络安全治理:零信任架构的创新实践与应用
  • 常见的图像生成模型
  • SystemUtils:你的Java系统“探照灯“——让环境探测不再盲人摸象
  • Flink流处理实战:实时对账与双流连接
  • inode 与 block 概念详解
  • 成都网站建设制作设计/2022新闻热点事件简短30条
  • ftp上传网站全教程/营销活动怎么做吸引人
  • app界面设计风格/西安分类信息seo公司
  • 网站怎么做分类聚合/关键词优化策略有哪些
  • 陇南网站设计/seo长尾快速排名
  • 小程序询价表/seo百度点击软件