A.2 高级数组操作
除花式索引、切片、布尔条件取子集等操作之外,数组的操作方式还有很多。虽然pandas中的高级函数可以处理数据分析工作中的许多重型任务,但有时你还是需要编写一些在现有库中找不到的数据算法。
数组重塑
多数情况下,你可以无需复制任何数据,就将数组从一个形状转换为另一个形状。只需向数组的实例方法reshape传入一个表示新形状的元组即可实现该目的。例如,假设有一个一维数组,我们希望将其重新排列为一个矩阵(结果见图A-3):
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yY5MDMxkDO1UzMlFmZjBjYhhjN1cjNlZWYhVjZxITO28CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
图A-3 按C顺序(按行)和按Fortran顺序(按列)进行重塑
多维数组也能被重塑:
作为参数的形状的其中一维可以是-1,它表示该维度的大小由数据本身推断而来:
与reshape将一维数组转换为多维数组的运算过程相反的运算通常称为扁平化(flattening)或散开(raveling):
如果结果中的值与原始数组相同,ravel不会产生源数据的副本。flatten方法的行为类似于ravel,只不过它总是返回数据的副本:
数组可以被重塑或散开为别的顺序。这对NumPy新手来说是一个比较微妙的问题,所以在下一小节中我们将专门讲解这个问题。
C和Fortran顺序
NumPy允许你更为灵活地控制数据在内存中的布局。默认情况下,NumPy数组是按行优先顺序创建的。在空间方面,这就意味着,对于一个二维数组,每行中的数据项是被存放在相邻内存位置上的。另一种顺序是列优先顺序,它意味着每列中的数据项是被存放在相邻内存位置上的。
由于一些历史原因,行和列优先顺序又分别称为C和Fortran顺序。在FORTRAN 77中,矩阵全都是列优先的。
像reshape和reval这样的函数,都可以接受一个表示数组数据存放顺序的order参数。一般可以是'C'或'F'(还有'A'和'K'等不常用的选项,具体请参考NumPy的文档)。图A-3对此进行了说明:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yY5MDMxkDO1UzMlFmZjBjYhhjN1cjNlZWYhVjZxITO28CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
图A-3 按C(行优先)或Fortran(列优先)顺序进行重塑
二维或更高维数组的重塑过程比较令人费解(见图A-3)。C和Fortran顺序的关键区别就是维度的行进顺序:
- C/行优先顺序:先经过更高的维度(例如,轴1会先于轴0被处理)。
- Fortran/列优先顺序:后经过更高的维度(例如,轴0会先于轴1被处理)。
数组的合并和拆分
numpy.concatenate
可以按指定轴将一个由数组组成的序列(如元组、列表等)连接到一起:
对于常见的连接操作,NumPy提供了一些比较方便的方法(如
vstack
和
hstack
)。因此,上面的运算还可以表达为:
与此相反,
split
用于将一个数组沿指定轴拆分为多个数组:
传入到np.split的值[1,3]指示在哪个索引处分割数组。
表A-1中列出了所有关于数组连接和拆分的函数,其中有些是专门为了方便常见的连接运算而提供的。
表A-1 数组连接函数
堆叠辅助类:r_和c_
NumPy命名空间中有两个特殊的对象——r_和c_,它们可以使数组的堆叠操作更为简洁:
它还可以将切片转换成数组:
r_和c_的具体功能请参考其文档。
元素的重复操作:tile和repeat
对数组进行重复以产生更大数组的工具主要是repeat和tile这两个函数。repeat会将数组中的各个元素重复一定次数,从而产生一个更大的数组:
❝
🦊 笔记:跟其他流行的数组编程语言(如MATLAB)不同,NumPy中很少需要对数组进行重复(replicate)。这主要是因为广播(broadcasting,我们将在下一节中讲解该技术)能更好地满足该需求。
❞
默认情况下,如果传入的是一个整数,则各元素就都会重复那么多次。如果传入的是一组整数,则各元素就可以重复不同的次数:
对于多维数组,还可以让它们的元素沿指定轴重复:
注意,如果没有设置轴向,则数组会被扁平化,这可能不会是你想要的结果。同样,在对多维进行重复时,也可以传入一组整数,这样就会使各切片重复不同的次数:
tile的功能是沿指定轴向堆叠数组的副本。你可以形象地将其想象成“铺瓷砖”:
第二个参数是瓷砖的数量。对于标量,瓷砖是水平铺设的,而不是垂直铺设。它可以是一个表示“铺设”布局的元组:
花式索引的等价函数:take和put
在第4章中我们讲过,获取和设置数组子集的一个办法是通过整数数组使用花式索引:
ndarray还有其它方法用于获取单个轴向上的选区:
要在其它轴上使用take,只需传入axis关键字即可:
put不接受axis参数,它只会在数组的扁平化版本(一维,C顺序)上进行索引。因此,在需要用其他轴向的索引设置元素时,最好还是使用花式索引。