Numpy数组与矩阵(二)
1 数组操作
在numpy中包含了一些处理数组的函数,大概可以分类成:
- 修改数组形状
- 翻转数组
- 修改数组维度
- 连接两个数组
- 分割数组
- 数组元素的添加与删除
1.1 修改数组形状
修改函数形状的函数如下:
函 数 | 描 述 |
---|---|
reshape | 不改变数据的条件下修改数组形状 |
flat | 数组元素的迭代器 |
flatten | 返回一份数组拷贝,对拷贝所做的修改不会影响原始数据 |
ravel | 返回展开的数组 |
我们重点介绍使用频率最高的reshape函数,这个函数的具体格式如下:
numpy.reshape(arr, newshape, order = 'C')
我们对reshape函数中的参数进行说明:
- arr:表示需要修改形状的数组名称;
- newshape:表示整数或者整数数组,需要注意的是,新的形状需要兼容我们的老数组;
- order:表示元素的顺序,C表示按行排序,F表示按列排序,A表示安装原顺序排序,K表示按照元素在内存中的出现顺序排序。
以下我们通过一个实例对reshape函数进行说明:
import numpy as np
a = np.arange(16)
print('old arrays:')
print(a)
b = a.reshape([4, 4])
print('new arrays:')
print(b)
###1.2 翻转数组
可以用来翻转数组的函数如下进行说明:
函 数 | 描 述 |
---|---|
transpose | 对换数组的维度 |
ndarray.T | 和self.transpose()相同 |
rollaxis | 向后滚动指定的轴 |
swapaxes | 对换数组的两个轴 |
同样地,我们对最重要的transpose函数进行说明,它的使用方法如下:
numpy.transpose(arr, axes)
我们对transpose函数中的参数进行说明:
- arr:需要操作的数组;
- axes:整数列表,对应维度,通常所有维度都会对换。
我们通过实例进行说明:
import numpy as np
a = np.arange(24).reshape(4, 6)
print('old arrays:')
print(a)
b = np.transpose(a)
print('new arrays:')
print(b)
当然,ndarray.T函数和numpy.transpose函数的功能是相似的,都是对数组进行转置操作,下面我们通过实例来了解这个函数。
import numpy as np
a = np.arange(36).reshape(4,9)
print('older arrays:')
print(a)
print('new arrays:')
print(a.T)
1.3 修改数组维度
可以用来修改数组维度的函数如下列表:
函 数 | 描 述 |
---|---|
broadcast | 产生模仿广播的对象 |
broadcast_to | 将数组广播到新形状 |
expand_dims | 扩展数组的形状 |
squeeze | 从数组的形状中删除以一维条目 |
广播(这个概念比较抽象,我的理解是传递,又或者是赋值 )是允许操作符或者函数对两个(或者多个)数组进行操作,即使这些数组的形状不同,但是需要注意的是,不是所有维度的数组都可以被广播,数组是需要遵循一定规则的。
Numpy的广播遵循一组严格的规则,这个规则是为了决定两个数组之间的操作。
- 规则1:如果连个数组的维度数不相同,那么小维度数组的形状将会在最左边补1;
- 规则2:如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度为1的维度扩展来匹配另外一个数组的形状;
- 规则3:如果两个数组的形状在任何一个维度上都不匹配并且没有任何一个维度等于1,那么会引发异常。
我们将会应用实例来说明实际广播的用法,我们需要两个数组。
import numpy as np
a = np.arange(9).reshape(3, 3)
print('a:')
print(a)
b = np.arange(3)
print('b:')
print(b)
print('a+b:')
print(a+b)
我们看到。a+b是将a数组的第一行和b数组相加,然后依托于a数组的维度,将已经相加过的一行数组放到a数组的第一行。这就是我们所说的广播。
当然,numpy.broadcast_to函数可以将数组广播到新的形状。在原始数组上只返回只读视图,但通常情况下是不连续的,如果新的形状不符合Numpy的广播规则,就会提示报错(ValueError)。
import nmupy as np
a = np.arange(4).reshape(1, 4)
print('older arrays:')
print(a)
print('Used broadcast_to arrays:')
print(np.broadcast_to(a, (4, 4)))
1.4 连接两个数组
连接数组的函数列表如下所示:
函 数 | 描 述 |
---|---|
concatenate | 实现数组的横向或者纵向合并,其中的参数axis=1时进行横向合并,axis=0时进行纵向合并 |
stack | 沿着新的轴加入一系列数组 |
hstack | 将数组横向合并(增加列的数量) |
vstack | 将数组纵向合并(增加行的数量) |
我们首先讲解concatenate函数的用法,语法格式如下:
numpy.concatenate((a1, a2, a3, ...),axis)
对其中的参数进行说明:
- a1, a2, a3, …:是相同数据类型的数组
- axis:为1时,进行横向合并;为0时,进行纵向合并。默认情况下是0
实例说明该函数的使用情况:
import numpy as np
a = np.array([[1, 2], [3, 4]])
print('第一个数组:')
print(a)
b = np.array([[5, 6], [7, 8]])
print('第二个数组:')
print(b)
我们首先将初始化两个数组,然后我们进行数组之间的合并,首先是横向合并(axis=1):
print('将两个数组进行横向合并(1):')
print(np.concatenate((a, b), axis = 1))
print('将两个数组进行横向合并(2):')
print(np.concatenate((b, a), axis = 1))
我们发现,在concatenate函数中,调换数组的顺序,会输出不同的合并数组出来。接下来我们进行纵向数组合并(axis=0):
print('将两个数组进行纵向合并(1):')
print(np.concatenate((a, b), axis = 0))
print('将两个数组进行纵向合并(2):')
print(np.concatenate((b, a), axis = 0))
对于纵向合并,同样地,数组未知的顺序调换,也会得到不同的合并数组。
1.5 分割数组
可以进行数组分隔的函数如下所示:
函数 | 数组及操作 |
---|---|
split | 将一个数组分割为多个子数组,有参数axis,axis=1时,实现横向分割;axis=0(也是默认值)时,实现纵向分割 |
hslipt | 将一个数组在水平方向上分割为几个子数组(按列) |
vsplit | 将一个数组在垂直方向上分割为几个子数组(按行) |
其中我们最常使用的是split函数,它的具体语法结构如下所示:
numpy.split(array, indices_or_sections, axis)
参数说明如下:
- array:将要被分割的数组的数组名
- indices_or_sections:若对这个参数定义了整数,就用这个数进行平均切分,如果是一个数组,就沿着轴的位置进行切分(左开右闭)
- axis:为1时,实现横向分割;为0时(也是默认值),实现纵向分割
实例说明:
import numpy as np
a = np.arange(12)
print('第一个数组:')
print(a)
print('将数组分成三个大小相等的数组:')
b = np.split(a, 4)
print(b)
print('将数组在一维数组中表明的位置分割:')
b = np.split(a, [4, 7])
print(b)
numpy.hsplit函数可以用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原始数组;numpy.vsplit可以沿着垂直方向进行分割,它的分割方式和hsplit用法相同。
我们通过实例来说明:
import numpy as np
a = np.arange(16).reshape(4, 4)
print('hsplit分割(水平分割):\n', np.hsplit(a, 2))
print('vsplit分割(垂直分割):\n', np.vsplit(a, 2))
1.6 数组元素的添加与删除
可以进行数组元素的添加与删除的函数列表:
函 数 | 描 述 |
---|---|
resize | 返回指定形状的新数组 |
append | 将值添加到数组末尾 |
insert | 沿着指定轴将值插入指定坐标之前 |
delete | 删除某个轴的子数组,并返回删除后的新数组 |
unique | 查找数组中的唯一元素 |
-
numpy.resize函数通过返回指定大小的新数组,如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
numpy.resize(arr, shape)
参数说明:
- arr:需要修改大小的数组;
- shape:应该返回的新数组形状。
import numpy as np a = np.array([[1, 2, 3],[4, 5, 6]]) print('原始数组:') print(a) print('原始数组的shape:') print(a.shape) b = np.resize(a, (3, 2)) print('第一次修改后的数组:') print(b) print('第一次修改后数组的shape:') print(b.shape) c = np.resize(a, (3, 5)) print('第二次修改后的数组:') print(c)
-
numpy.append函数在数组的末尾添加值,追加操作会分配给整个数组,并且会把原来的数组复制到新的数组中,除此之外,输入的数组维度必须要匹配,否则会报ValueError。
numpy.append(arr, values, axis = None)
参数说明如下:
- arr:进行操作的数组;
- values:需要向arr中添加的值,需要和arr的形状相同(除了我们需要添加的轴);
- axis:默认为None,当axis无定义是,是横向加成,返回的是一维数组;当axis = 0时(列数不改变),数组添加在下方;当axis= 1时(行数不改变),数组添加在右方。
import numpy as np a = np.array([[1, 2, 3], [4, 5, 6]]) print('原始数组:') print(a) print('向a数组中添加元素:') print(np.append(a, [7, 8, 9])) print('沿0轴添加元素(列数不改变):') print(np.append(a, [[5, 5, 5], [7, 8, 9]], axis= 0)) print('沿1轴添加元素(行数不改变):') print(np.append(a, [[5, 5, 5], [7, 8, 9]], axis= 1))
-
numpy.insert函数在给定索引之前,沿着定轴在输入数组中插入值,需要注意的是如果没有提供轴的参数,那么输入数组就会展开。
numpy.insert(arr, obj, values, axis)
参数说明如下:
- arr:输入数组;
- obj:在其之前插入数据的索引;
- values:需要插入的值;
- axis:沿着它插入的轴,没有提供,输入数组就会展开,变成一维数组。
import numpy as np a = np.array([[1, 2], [3, 4], [5, 6]]) print('原始数组:') print(a) print('没有传递axis参数,在插入之前输入数组a会被展开成一维数组:') print(np.insert(a, 3, [99, 100])) print('传递axis参数,会产生新的数组:') print('沿0轴广播(列数不发生变化):') print(np.insert(a, 1, [11], axis = 0)) print('沿1轴广播(行数不发生变化):') print(np.insert(a, 2, [11], axis = 1))
-
numpy。delete函数返回从输入数组中删除指定子数组的新数组,和insert函数的情况一样,如果没有提交轴参数(axis),就会把输入的数组展开成一维数组。
numpy.delete(arr, obj, axis)
参数说明:
- arr:输入数组;
- obj:指定子数组的位置,可以是切片、整数或者是整数数组,表名要从指定位置删除子数组;
- axis:沿着axis删除给定子数组的轴,如果没有提供,输入数组会展开为一维数组。
import numpy as np a = np.arange(15).reshape(3, 5) print('原始数组:') print(a) print('没有传递axis,在插入之前将输入函数一维展开:') print(np.delete(a, 8)) print('删除第二列:') print(np.delete(a, 1, axis = 1))
-
numpy.unique函数可以用来去除数组中的重复元素,
numpy.unique(arr, return_index, return_inverse, return_counts)
参数说明:
- arr:输入数组,如果不是一维数组,则会展开。
- return_index:如果是True,返回新列表元素在旧列表中的位置(下标),并以列表形式存储;
- return_inverse:如果是True,返回旧列表元素在新列表中的位置(下标),并以列表形式存储;
- return_counts:如果是True,返回去重数组中的元素在原数组中的出现次数。
import numpy as np a = np.array([1, 2, 3, 3, 10, 2, 4, 5, 4, 8, 7, 2, 7, 5, 9, 10 ,2]) print('输出a数组:') print(a) print('去重后的a数组:') b = np.unique(a) print(b) print('去重数组a的索引数组:') b, indices = np.unique(a, return_index = True) print(indices) print('返回去重数组的重复数量:') c, indices = np.unique(a, return_counts = True) print(c) print(indices)