NumPy 数组创建

2021-09-03 18:28 更新

介绍

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

  • 从其他 Python 结构(即列表和元组)转换
  • 内在的 NumPy 数组创建函数(例如 arange、1、0 等)
  • 复制、加入或改变现有数组
  • 从磁盘读取数组,无论是标准格式还是自定义格式
  • 通过使用字符串或缓冲区从原始字节创建数组
  • 使用特殊库函数(例如,random)

可以使用这些方法来创建 ndarrays 或Structured arrays。本文档将介绍创建 ndarray 的一般方法。

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

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

  • 一个数字列表将创建一个一维数组,
  • 列表的列表将创建一个二维数组,
  • 进一步的嵌套列表将创建更高维的数组。通常,任何数组对象在 NumPy 中都称为ndarray。

>>> 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,可以明确指定。此功能可以更好地控制底层数据结构以及如何在 C/C++ 函数中处理元素。如果你不小心指定了dtype,可能会遇到不必要的溢出,因此:

>>> a = np.array([127, 128, 129], dtype=np.int8)
>>> a
array([ 127, -128, -127], dtype=int8)

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

>>> a = array([2, 3, 4], dtype = np.uint32)
>>> b = 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

请注意:当对两个相同的dtypeuint32数组执行操作时,结果数组的类型相同。当使用不同的dtype执行操作时,NumPy 将分配一个新类型,该类型满足计算中涉及的所有数组元素,在这里uint32int32都可以表示为int64

默认的 NumPy 行为是分别以 64 位有符号整数或双精度浮点数int64和 来创建数组float。如果您希望数组是某种类型,那么您需要指定dtype创建数组的时间。

2、内在的 NumPy 数组创建函数

NumPy 有超过 40 个用于创建数组的内置函数,如数组创建例程中所述。这些函数可以根据它们创建的数组的维度大致分为三类:

  1. 一维数组
  2. 二维数组
  3. 数组

2.1 一维数组创建函数

一维数组创建函数例如numpy.linspace并且 numpy.arange通常需要至少两个输入,start和 stop

numpy.arange创建具有定期递增值的数组。查看文档以获取完整信息和示例。显示了一些示例:

>>> 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被定义了 。在第三个示例中,数组 dtype=float将容纳0.1的步长。由于舍入误差,stop有时会包含该值。

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

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

2.2 二维数组创建函数

二维数组创建函数例如numpy.eyenumpy.diagnumpy.vander 定义表示为二维数组的特殊矩阵的属性。

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

>>> 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可以定义具有沿对角线给定值的方形二维数组,或者如果给定二维数组,则返回仅包含对角元素的一维数组。这两个数组创建函数在进行线性代数时会很有帮助,例如:

>>> 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)将 Vandermonde 矩阵定义为 2D NumPy 数组。Vandermonde 矩阵的每一列都是输入一维数组或列表或元组的递减幂, x其中最高多项式阶为n-1。此数组创建例程有助于生成线性最小二乘模型,例如:

>>> np.vander(np.linspace(0, 2, 5), 2)
array([[0.  , 0.  , 1.  ],
       [0.25, 0.5 , 1.  ],
       [1.  , 1.  , 1.  ],
       [2.25, 1.5 , 1.  ],
       [4.  , 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]])

2.3 一般 ndarray 创建函数

ndarray 创建函数,例如numpy.onesnumpy.zeros,并random根据所需的形状定义数组。ndarray 创建函数可以通过指定元组或列表中沿该维度的维度和长度来创建具有任何维度的数组。

numpy.zeros将创建一个用指定形状填充 0 值的数组。默认数据类型为float64

>>> 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在所有其他方面都相同, 例如:

>>> 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.]]])

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

>>> import numpy.random.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 将创建一组数组(堆叠为一个更高维度的数组),每个维度一个,每个代表该维度的变化:

>>> 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该数组,否则该变量是原始数组的视图。考虑以下示例:

>>> 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中的前两个元素. 当将 1 添加到b时,将通过将 1 添加到a[:2]得到相同的结果。如果要创建新数组,请使用numpy.copy数组创建例程,如下所示:

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

有关更多信息和示例,请查看副本和视图。 有许多程序加入现有阵列例如numpy.vstack, numpy.hstacknumpy.block。下面是一个使用 将四个 2×2 数组连接成一个 4×4 数组的示例block

>>> 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. ]])

其他例程使用类似的语法来连接 ndarrays。检查例程的文档以获取更多示例和语法。

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

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

4.1 标准二进制格式

各种字段都有数组数据的标准格式。下面列出了具有已知 Python 库以读取它们并返回 NumPy 数组的那些(可能还有其他一些可以读取并转换为 NumPy 数组,因此也请检查最后一节)

HDF5: h5py
FITS: Astropy

无法直接读取但不难转换的格式示例是 PIL 等库支持的格式(能够读取和写入许多图像格式,例如 jpg、png 等)。

4.2 常见的 ASCII 格式

逗号分隔值 (csv) 和制表符分隔值 (tsv) 文件等分隔文件用于 Excel 和 LabView 等程序。Python 函数可以逐行读取和解析这些文件。NumPy 有两个标准例程用于导入带有分隔数据numpy.loadtxt 和numpy.genfromtxt. 这些函数在读写文件中有更多涉及的用例 。给出一个简单的例子simple.csv

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

导入simple.csv是使用loadtxt以下方法完成的:

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

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

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

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

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

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

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号