Python 金融编程第二版(二)(1)

简介: Python 金融编程第二版(二)

第四章:使用 NumPy 进行数值计算

计算机是无用的。它们只能给出答案。

巴勃罗·毕加索

介绍

本章介绍了 Python基本数据类型和数据结构。尽管 Python 解释器本身已经带来了丰富的数据结构,但 NumPy 和其他库以有价值的方式添加了这些数据结构。

本章组织如下:

数据数组

本节详细讨论了数组的概念,并说明了在 Python 中处理数据数组的基本选项。

NumPy 数据结构

本节致力于介绍 NumPy ndarray 类的特性和功能,并展示了该类对科学和金融应用的一些好处。

代码向量化

本节说明了,由于 NumPy 的数组类,向量化代码很容易实现,从而导致代码更紧凑,性能更好。

本章涵盖了以下数据结构:

对象类型 含义 用法/模型
ndarray(常规) n 维数组对象 大量数值数据的大数组
ndarray(记录) 二维数组对象 以列组织的表格数据

本章组织如下:

“数据数组”

本节讨论了使用纯 Python 代码处理数据数组的方法。

[待添加链接]

这是关于常规 NumPy ndarray 类的核心部分;它是几乎所有数据密集型 Python 使用案例中的主要工具。

[待添加链接]

这个简短的部分介绍了用于处理带有列的表格数据的结构化(或记录)ndarray 对象。

“代码的向量化”

在本节中,讨论了代码的向量化及其好处;该部分还讨论了在某些情况下内存布局的重要性。

数据数组

前一章表明 Python 提供了一些非常有用和灵活的通用数据结构。特别是,list  对象可以被认为是一个真正的工作马,具有许多方便的特性和应用领域。在一般情况下,使用这样一个灵活的(可变的)数据结构的代价在于相对较高的内存使用量,较慢的性能或两者兼有。然而,科学和金融应用通常需要对特殊数据结构进行高性能操作。在这方面最重要的数据结构之一是数组。数组通常以行和列的形式结构化其他(基本)相同数据类型的对象。

暂时假设我们仅使用数字,尽管这个概念也可以推广到其他类型的数据。在最简单的情况下,一维数组在数学上表示为向量,通常由float对象内部表示为实数的一行或一列元素组成。在更普遍的情况下,数组表示为i × j 矩阵的元素。这个概念在三维中也可以推广为i × j × k 立方体的元素以及形状为i × j × k × l × …的一般n维数组。

线性代数和向量空间理论等数学学科说明了这些数学结构在许多科学学科和领域中的重要性。因此,设计一个专门的数据结构类来方便和高效地处理数组可能是非常有益的。这就是PythonNumPy的作用所在,其ndarray类应运而生。在下一节介绍其强大的ndarray类之前,本节展示了两种处理数组的替代方法。

使用 Python 列表的数组

在转向NumPy之前,让我们首先用上一节介绍的内置数据结构构建数组。list对象特别适用于完成这项任务。一个简单的list已经可以被视为一维数组:

In [1]: v = [0.5, 0.75, 1.0, 1.5, 2.0]  # ①

list对象与数字。

由于list对象可以包含任意其他对象,它们也可以包含其他list对象。通过嵌套list对象,可以轻松构建二维和更高维的数组:

In [2]: m = [v, v, v]  # ①
        m  # ②
Out[2]: [[0.5, 0.75, 1.0, 1.5, 2.0],
         [0.5, 0.75, 1.0, 1.5, 2.0],
         [0.5, 0.75, 1.0, 1.5, 2.0]]

list对象与list对象…

… 得到一个数字矩阵。

我们还可以通过简单的索引选择行或通过双重索引选择单个元素(然而,选择整列并不那么容易):

In [3]: m[1]
Out[3]: [0.5, 0.75, 1.0, 1.5, 2.0]
In [4]: m[1][0]
Out[4]: 0.5

嵌套可以进一步推广到更一般的结构:

In [5]: v1 = [0.5, 1.5]
        v2 = [1, 2]
        m = [v1, v2]
        c = [m, m]  # ①
        c
Out[5]: [[[0.5, 1.5], [1, 2]], [[0.5, 1.5], [1, 2]]]
In [6]: c[1][1][0]
Out[6]: 1

立方数。

请注意,刚刚介绍的对象组合方式通常使用对原始对象的引用指针。这在实践中意味着什么?让我们看看以下操作:

In [7]: v = [0.5, 0.75, 1.0, 1.5, 2.0]
        m = [v, v, v]
        m
Out[7]: [[0.5, 0.75, 1.0, 1.5, 2.0],
         [0.5, 0.75, 1.0, 1.5, 2.0],
         [0.5, 0.75, 1.0, 1.5, 2.0]]

现在修改v对象的第一个元素的值,看看m对象会发生什么变化:

In [8]: v[0] = 'Python'
        m
Out[8]: [['Python', 0.75, 1.0, 1.5, 2.0],
         ['Python', 0.75, 1.0, 1.5, 2.0],
         ['Python', 0.75, 1.0, 1.5, 2.0]]

通过使用copy模块的deepcopy函数,可以避免这种情况:

In [9]: from copy import deepcopy
        v = [0.5, 0.75, 1.0, 1.5, 2.0]
        m = 3 * [deepcopy(v), ]  # ①
        m
Out[9]: [[0.5, 0.75, 1.0, 1.5, 2.0],
         [0.5, 0.75, 1.0, 1.5, 2.0],
         [0.5, 0.75, 1.0, 1.5, 2.0]]
In [10]: v[0] = 'Python'  # ②
         m  # ③
Out[10]: [[0.5, 0.75, 1.0, 1.5, 2.0],
          [0.5, 0.75, 1.0, 1.5, 2.0],
          [0.5, 0.75, 1.0, 1.5, 2.0]]

使用物理副本而不是引用指针。

因此,对原始对象的更改…

… 不再有任何影响。

Python 数组类

Python 中有一个专用的array模块可用。正如您可以在文档页面上阅读到的(参见https://docs.python.org/3/library/array.html):

该模块定义了一种对象类型,可以紧凑地表示基本值的数组:字符、整数、浮点数。数组是序列类型,并且行为非常像列表,只是存储在其中的对象类型受到限制。类型在对象创建时通过使用类型代码(一个单个字符)来指定。

考虑以下代码,将一个list对象实例化为一个array对象。

In [11]: v = [0.5, 0.75, 1.0, 1.5, 2.0]
In [12]: import array
In [13]: a = array.array('f', v)  # ①
         a
Out[13]: array('f', [0.5, 0.75, 1.0, 1.5, 2.0])
In [14]: a.append(0.5)  # ②
         a
Out[14]: array('f', [0.5, 0.75, 1.0, 1.5, 2.0, 0.5])
In [15]: a.extend([5.0, 6.75])  # ②
         a
Out[15]: array('f', [0.5, 0.75, 1.0, 1.5, 2.0, 0.5, 5.0, 6.75])
In [16]: 2 * a  # ③
Out[16]: array('f', [0.5, 0.75, 1.0, 1.5, 2.0, 0.5, 5.0, 6.75, 0.5, 0.75, 1.0, 1.5, 2.0, 0.5, 5.0, 6.75])

使用float作为类型代码实例化array对象。

主要方法的工作方式类似于list对象的方法。

虽然“标量乘法”原理上可行,但结果不是数学上预期的;而是元素被重复。

尝试附加与指定数据类型不同的对象会引发TypeError

In [17]: # a.append('string') # ①
In [18]: a.tolist()  # ②
Out[18]: [0.5, 0.75, 1.0, 1.5, 2.0, 0.5, 5.0, 6.75]

仅能附加float对象;其他数据类型/类型代码会引发错误。

然而,如果需要这样的灵活性,array对象可以轻松转换回list对象。

array类的一个优点是它具有内置的存储和检索功能。

In [19]: f = open('array.apy', 'wb')  # ①
         a.tofile(f)  # ②
         f.close()  # ③
In [20]: with open('array.apy', 'wb') as f:  # ④
             a.tofile(f)  # ④
In [21]: !ls -n arr*  # ⑤
         -rw-r--r--@ 1 503  20  32 29 Dez 17:08 array.apy

打开一个用于写入二进制数据的磁盘上的文件。

array数据写入文件。

关闭文件。

或者,可以使用with上下文执行相同的操作。

这显示了磁盘上写入的文件。

与以前一样,从磁盘读取数据时,array对象的数据类型很重要。

In [22]: b = array.array('f')  # ①
In [23]: with open('array.apy', 'rb') as f:  # ②
             b.fromfile(f, 5)  # ③
In [24]: b  # ④
Out[24]: array('f', [0.5, 0.75, 1.0, 1.5, 2.0])
In [25]: b = array.array('d')  # ⑤
In [26]: with open('array.apy', 'rb') as f:
             b.fromfile(f, 2)  # ⑥
In [27]: b  # ⑦
Out[27]: array('d', [0.0004882813645963324, 0.12500002956949174])

使用类型代码float创建一个新的array对象。

打开文件以读取二进制数据…

…并在b对象中读取五个元素。

使用类型代码double创建一个新的array对象。

从文件中读取两个元素。

类型代码的差异导致“错误”的数字。

常规 NumPy 数组

显然,使用list对象构成数组结构有些作用。但这并不是真正方便的方式,而且list类并没有为此特定目标而构建。它的范围更广泛,更一般。array类已经稍微更专业一些,提供了一些有用的特性来处理数据数组。然而,某种“高度”专业化的类因此可能真的对处理数组类型的结构非常有益。

基础知识

这样一个专门的类就是numpy.ndarray类,它的特定目标是方便且高效地处理n维数组,即以高性能的方式。这个类的基本处理最好通过示例来说明:

In [28]: import numpy as np  # ①
In [29]: a = np.array([0, 0.5, 1.0, 1.5, 2.0])  # ②
         a
Out[29]: array([ 0. ,  0.5,  1. ,  1.5,  2. ])
In [30]: type(a)  # ②
Out[30]: numpy.ndarray
In [31]: a = np.array(['a', 'b', 'c'])  # ③
         a
Out[31]: array(['a', 'b', 'c'],
               dtype='<U1')
In [32]: a = np.arange(2, 20, 2)  # ④
         a
Out[32]: array([ 2,  4,  6,  8, 10, 12, 14, 16, 18])
In [33]: a = np.arange(8, dtype=np.float)  # ⑤
         a
Out[33]: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.])
In [34]: a[5:]  # ⑥
Out[34]: array([ 5.,  6.,  7.])
In [35]: a[:2]  # ⑥
Out[35]: array([ 0.,  1.])

导入numpy包。

通过list对象中的浮点数创建一个ndarray对象。

通过list对象中的字符串创建一个ndarray对象。

np.arange的工作方式类似于range

然而,它接受附加输入dtype参数。

对于一维的ndarray对象,索引的工作方式与平常一样。

ndarray类的一个重要特性是内置方法的多样性。例如:

In [36]: a.sum()  # ①
Out[36]: 28.0
In [37]: a.std()  # ②
Out[37]: 2.2912878474779199
In [38]: a.cumsum()  # ③
Out[38]: array([  0.,   1.,   3.,   6.,  10.,  15.,  21.,  28.])

所有元素的总和。

元素的标准偏差。

所有元素的累积和(从索引位置 0 开始)。

另一个重要特性是对ndarray对象定义的(向量化的)数学运算

In [39]: l = [0., 0.5, 1.5, 3., 5.]
         2 * l  # ①
Out[39]: [0.0, 0.5, 1.5, 3.0, 5.0, 0.0, 0.5, 1.5, 3.0, 5.0]
In [40]: a
Out[40]: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.])
In [41]: 2 * a  # ②
Out[41]: array([  0.,   2.,   4.,   6.,   8.,  10.,  12.,  14.])
In [42]: a ** 2  # ③
Out[42]: array([  0.,   1.,   4.,   9.,  16.,  25.,  36.,  49.])
In [43]: 2 ** a  # ④
Out[43]: array([   1.,    2.,    4.,    8.,   16.,   32.,   64.,  128.])
In [44]: a ** a  # ⑤
Out[44]: array([  1.00000000e+00,   1.00000000e+00,   4.00000000e+00,
                  2.70000000e+01,   2.56000000e+02,   3.12500000e+03,
                  4.66560000e+04,   8.23543000e+05])

list对象的“标量乘法”导致元素的重复。

相比之下,使用ndarray对象实现了适当的标量乘法,例如。

这个计算每个元素的平方值。

这解释了ndarray的元素作为幂。

这个计算每个元素的自身的幂。

NumPy包的另一个重要功能是通用函数。它们在一般情况下对ndarray对象以及基本 Python 数据类型进行操作。然而,当将通用函数应用于 Python float对象时,需要注意与math模块中相同功能的性能降低。

In [45]: np.exp(a)  # ①
Out[45]: array([  1.00000000e+00,   2.71828183e+00,   7.38905610e+00,
                  2.00855369e+01,   5.45981500e+01,   1.48413159e+02,
                  4.03428793e+02,   1.09663316e+03])
In [46]: np.sqrt(a)  # ②
Out[46]: array([ 0.        ,  1.        ,  1.41421356,  1.73205081,  2.        ,
                 2.23606798,  2.44948974,  2.64575131])
In [47]: np.sqrt(2.5)  # ③
Out[47]: 1.5811388300841898
In [48]: import math  # ④
In [49]: math.sqrt(2.5)  # ④
Out[49]: 1.5811388300841898
In [50]: # math.sqrt(a) # ⑤
In [51]: %timeit np.sqrt(2.5)  # ⑥
         703 ns ± 17.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [52]: %timeit math.sqrt(2.5)  # ⑦
         107 ns ± 1.48 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

逐个元素计算指数值。

计算每个元素的平方根。

计算 Python float对象的平方根。

相同的计算,这次使用math模块。

math.sqrt不能直接应用于ndarray对象。

将通用函数np.sqrt应用于 Python float对象……

……比使用math.sqrt函数的相同操作慢得多。

多维度

切换到多维度是无缝的,并且到目前为止呈现的所有特征都适用于更一般的情况。特别是,索引系统在所有维度上保持一致:

In [53]: b = np.array([a, a * 2])  # ①
         b
Out[53]: array([[  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.],
                [  0.,   2.,   4.,   6.,   8.,  10.,  12.,  14.]])
In [54]: b[0]  # ②
Out[54]: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.])
In [55]: b[0, 2]  # ③
Out[55]: 2.0
In [56]: b[:, 1]  # ④
Out[56]: array([ 1.,  2.])
In [57]: b.sum()  # ⑤
Out[57]: 84.0
In [58]: b.sum(axis=0)  # ⑥
Out[58]: array([  0.,   3.,   6.,   9.,  12.,  15.,  18.,  21.])
In [59]: b.sum(axis=1)  # ⑦
Out[59]: array([ 28.,  56.])

用一维数组构造二维ndarray对象。

选择第一行。

选择第一行的第三个元素;在括号内,索引由逗号分隔。

选择第二列。

计算所有值的总和。

沿第一个轴计算总和,即按列计算。

沿第二轴计算总和,即按行计算。

有多种方法可以初始化(实例化)ndarray对象。一种方法如前所述,通过np.array。然而,这假定数组的所有元素已经可用。相比之下,也许我们希望首先实例化ndarray对象,以便在执行代码期间生成的结果后来填充它们。为此,我们可以使用以下函数:

In [60]: c = np.zeros((2, 3), dtype='i', order='C')  # ①
         c
Out[60]: array([[0, 0, 0],
                [0, 0, 0]], dtype=int32)
In [61]: c = np.ones((2, 3, 4), dtype='i', order='C')  # ②
         c
Out[61]: array([[[1, 1, 1, 1],
                 [1, 1, 1, 1],
                 [1, 1, 1, 1]],
                [[1, 1, 1, 1],
                 [1, 1, 1, 1],
                 [1, 1, 1, 1]]], dtype=int32)
In [62]: d = np.zeros_like(c, dtype='f16', order='C')  # ③
         d
Out[62]: array([[[ 0.0,  0.0,  0.0,  0.0],
                 [ 0.0,  0.0,  0.0,  0.0],
                 [ 0.0,  0.0,  0.0,  0.0]],
                [[ 0.0,  0.0,  0.0,  0.0],
                 [ 0.0,  0.0,  0.0,  0.0],
                 [ 0.0,  0.0,  0.0,  0.0]]], dtype=float128)
In [63]: d = np.ones_like(c, dtype='f16', order='C')  # ③
         d
Out[63]: array([[[ 1.0,  1.0,  1.0,  1.0],
                 [ 1.0,  1.0,  1.0,  1.0],
                 [ 1.0,  1.0,  1.0,  1.0]],
                [[ 1.0,  1.0,  1.0,  1.0],
                 [ 1.0,  1.0,  1.0,  1.0],
                 [ 1.0,  1.0,  1.0,  1.0]]], dtype=float128)
In [64]: e = np.empty((2, 3, 2))  # ④
         e
Out[64]: array([[[  0.00000000e+000,  -4.34540174e-311],
                 [  2.96439388e-323,   0.00000000e+000],
                 [  0.00000000e+000,   1.16095484e-028]],
                [[  2.03147708e-110,   9.67661175e-144],
                 [  9.80058441e+252,   1.23971686e+224],
                 [  4.00695466e+252,   8.34404939e-309]]])
In [65]: f = np.empty_like(c)  # ④
         f
Out[65]: array([[[0, 0, 0, 0],
                 [9, 0, 0, 0],
                 [0, 0, 0, 0]],
                [[0, 0, 0, 0],
                 [0, 0, 0, 0],
                 [0, 0, 0, 0]]], dtype=int32)
In [66]: np.eye(5)  # ⑤
Out[66]: array([[ 1.,  0.,  0.,  0.,  0.],
                [ 0.,  1.,  0.,  0.,  0.],
                [ 0.,  0.,  1.,  0.,  0.],
                [ 0.,  0.,  0.,  1.,  0.],
                [ 0.,  0.,  0.,  0.,  1.]])
In [67]: g = np.linspace(5, 15, 15) # ⑥
         g
Out[67]: array([  5.        ,   5.71428571,   6.42857143,   7.14285714,
                  7.85714286,   8.57142857,   9.28571429,  10.        ,
                 10.71428571,  11.42857143,  12.14285714,  12.85714286,
                 13.57142857,  14.28571429,  15.        ])

用零预先填充的ndarray对象。

用 1 预先填充的ndarray对象。

相同,但采用另一个ndarray对象来推断形状。

ndarray对象不预先填充任何内容(数字取决于内存中存在的位)。

创建一个由 1 填充对角线的方阵作为ndarray对象。

创建一个一维ndarray对象,其中数字之间的间隔均匀分布;所使用的参数是startendnum(元素数量)。

使用所有这些函数,我们可以提供以下参数:

shape

要么是一个int,一个``int+s序列,或者是对另一个+numpy.ndarray的引用

dtype(可选)

一个dtype——这些是NumPy特定的numpy.ndarray对象的数据类型

order(可选)

存储元素在内存中的顺序:C表示C风格(即,逐行),或F表示Fortran风格(即,逐列)

在这里,NumPy如何通过ndarray类专门构建数组的方式,与基于list的方法进行比较变得明显:

  • ndarray对象具有内置的维度(轴)。
  • ndarray对象是不可变的,其形状是固定的。
  • 它仅允许单一数据类型numpy.dtype)用于整个数组。

相反,array类只共享允许唯一数据类型(类型代码,dtype)的特性。

order参数的作用在本章稍后讨论。表 4-1 提供了numpy.dtype对象的概述(即,NumPy允许的基本数据类型)。

表 4-1。NumPy dtype 对象

dtype 描述 示例
t 位域 t4 (4 位)
b 布尔 b(true 或 false)
i 整数 i8 (64 位)
u 无符号整数 u8 (64 位)
f 浮点数 f8 (64 位)
c 复数浮点数 c16 (128 位)
O 对象 0 (对象指针)
S, a 字符串 S24 (24 个字符)
U Unicode U24 (24 个 Unicode 字符)
V 其他 V12 (12 字节数据块)

元信息

每个ndarray对象都提供访问一些有用属性的功能。

In [68]: g.size  # ①
Out[68]: 15
In [69]: g.itemsize  # ②
Out[69]: 8
In [70]: g.ndim  # ③
Out[70]: 1
In [71]: g.shape  # ④
Out[71]: (15,)
In [72]: g.dtype  # ⑤
Out[72]: dtype('float64')
In [73]: g.nbytes  # ⑥
Out[73]: 120

元素的数量。

用于表示一个元素所使用的字节数。

维度的数量。

ndarray对象的形状。

元素的dtype

内存中使用的总字节数。

重塑和调整大小

虽然ndarray对象默认是不可变的,但有多种选项可以重塑和调整此类对象。一般情况下,第一个操作只是提供相同数据的另一个视图,而第二个操作一般会创建一个新的(临时)对象。

In [74]: g = np.arange(15)
In [75]: g
Out[75]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
In [76]: g.shape  # ①
Out[76]: (15,)
In [77]: np.shape(g) # ①
Out[77]: (15,)
In [78]: g.reshape((3, 5))  # ②
Out[78]: array([[ 0,  1,  2,  3,  4],
                [ 5,  6,  7,  8,  9],
                [10, 11, 12, 13, 14]])
In [79]: h = g.reshape((5, 3))  # ③
         h
Out[79]: array([[ 0,  1,  2],
                [ 3,  4,  5],
                [ 6,  7,  8],
                [ 9, 10, 11],
                [12, 13, 14]])
In [80]: h.T  # ④
Out[80]: array([[ 0,  3,  6,  9, 12],
                [ 1,  4,  7, 10, 13],
                [ 2,  5,  8, 11, 14]])
In [81]: h.transpose()  # ④
Out[81]: array([[ 0,  3,  6,  9, 12],
                [ 1,  4,  7, 10, 13],
                [ 2,  5,  8, 11, 14]])

原始ndarray对象的形状。

重塑为两个维度(内存视图)。

创建新对象。

ndarray对象的转置。

在重塑操作期间,ndarray对象中的元素总数保持不变。在调整大小操作期间,此数字会更改,即它要么减少(“向下调整”),要么增加(“向上调整”)。

In [82]: g
Out[82]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
In [83]: np.resize(g, (3, 1))  # ①
Out[83]: array([[0],
                [1],
                [2]])
In [84]: np.resize(g, (1, 5))  # ①
Out[84]: array([[0, 1, 2, 3, 4]])
In [85]: np.resize(g, (2, 5))  # ①
Out[85]: array([[0, 1, 2, 3, 4],
                [5, 6, 7, 8, 9]])
In [86]: n = np.resize(g, (5, 4))  # ②
         n
Out[86]: array([[ 0,  1,  2,  3],
                [ 4,  5,  6,  7],
                [ 8,  9, 10, 11],
                [12, 13, 14,  0],
                [ 1,  2,  3,  4]])

两个维度,向下调整。

两个维度,向上调整。

堆叠是一种特殊操作,允许水平或垂直组合两个ndarray对象。但是,“连接”维度的大小必须相同。

In [87]: h
Out[87]: array([[ 0,  1,  2],
                [ 3,  4,  5],
                [ 6,  7,  8],
                [ 9, 10, 11],
                [12, 13, 14]])
In [88]: np.hstack((h, 2 * h))  # ①
Out[88]: array([[ 0,  1,  2,  0,  2,  4],
                [ 3,  4,  5,  6,  8, 10],
                [ 6,  7,  8, 12, 14, 16],
                [ 9, 10, 11, 18, 20, 22],
                [12, 13, 14, 24, 26, 28]])
In [89]: np.vstack((h, 0.5 * h))  # ②
Out[89]: array([[  0. ,   1. ,   2. ],
                [  3. ,   4. ,   5. ],
                [  6. ,   7. ,   8. ],
                [  9. ,  10. ,  11. ],
                [ 12. ,  13. ,  14. ],
                [  0. ,   0.5,   1. ],
                [  1.5,   2. ,   2.5],
                [  3. ,   3.5,   4. ],
                [  4.5,   5. ,   5.5],
                [  6. ,   6.5,   7. ]])

水平堆叠两个ndarray对象。

垂直堆叠两个ndarray对象。

另一个特殊操作是将多维ndarray对象展平为一维对象。可以选择是按行(C顺序)还是按列(F顺序)进行展平。

In [90]: h
Out[90]: array([[ 0,  1,  2],
                [ 3,  4,  5],
                [ 6,  7,  8],
                [ 9, 10, 11],
                [12, 13, 14]])
In [91]: h.flatten()  # ①
Out[91]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
In [92]: h.flatten(order='C')  # ①
Out[92]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
In [93]: h.flatten(order='F')  # ②
Out[93]: array([ 0,  3,  6,  9, 12,  1,  4,  7, 10, 13,  2,  5,  8, 11, 14])
In [94]: for i in h.flat:  # ③
             print(i, end=',')
         0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
In [95]: for i in h.ravel(order='C'):  # ④
             print(i, end=',')
         0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
In [96]: for i in h.ravel(order='F'):  # ④
             print(i, end=',')
         0,3,6,9,12,1,4,7,10,13,2,5,8,11,14,

平铺的默认顺序是C

F顺序展平。

flat属性提供了一个平坦的迭代器(C顺序)。

ravel()方法是flatten()的另一种选择。


Python 金融编程第二版(二)(2)https://developer.aliyun.com/article/1559403

相关文章
|
4天前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
10天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
10天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
10天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
1天前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
4天前
|
存储 人工智能 数据挖掘
Python编程入门:打造你的第一个程序
本文旨在为初学者提供Python编程的初步指导,通过介绍Python语言的基础概念、开发环境的搭建以及一个简单的代码示例,帮助读者快速入门。文章将引导你理解编程思维,学会如何编写、运行和调试Python代码,从而开启编程之旅。
26 2
|
5天前
|
存储 Python
Python编程入门:理解基础语法与编写简单程序
本文旨在为初学者提供一个关于如何开始使用Python编程语言的指南。我们将从安装Python环境开始,逐步介绍变量、数据类型、控制结构、函数和模块等基本概念。通过实例演示和练习,读者将学会如何编写简单的Python程序,并了解如何解决常见的编程问题。文章最后将提供一些资源,以供进一步学习和实践。
15 1
|
8天前
|
存储 网络协议 IDE
从零起步学习Python编程
从零起步学习Python编程
|
11天前
|
机器学习/深度学习 存储 算法
探索Python编程:从基础到高级应用
【10月更文挑战第38天】本文旨在引导读者从Python的基础知识出发,逐渐深入到高级编程概念。通过简明的语言和实际代码示例,我们将一起探索这门语言的魅力和潜力,理解它如何帮助解决现实问题,并启发我们思考编程在现代社会中的作用和意义。
|
6天前
|
机器学习/深度学习 存储 数据挖掘
Python 编程入门:理解变量、数据类型和基本运算
【10月更文挑战第43天】在编程的海洋中,Python是一艘易于驾驭的小船。本文将带你启航,探索Python编程的基础:变量的声明与使用、丰富的数据类型以及如何通过基本运算符来操作它们。我们将从浅显易懂的例子出发,逐步深入到代码示例,确保即使是零基础的读者也能跟上步伐。准备好了吗?让我们开始吧!
16 0
下一篇
无影云桌面