文章目录
一、Ndarray对象
NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。ndarray 对象是用于存放同类型元素的多维数组。
二、数据类型
numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,如np.bool_,np.int32等。
三、创建数组
1. numpy.array(object, dtype=None, copy=True, order=None, subok=Flase, ndmin=0)
- object:数组或嵌套的数列
- dtype:数组元素的数据类型,可选
- copy :对象是否需要复制,可选
- order :在计算机内存中的存储元素的顺序,C为行方向,F为列方向,A为任意方向(默认)
- subok:默认返回一个与基类类型一致的数组
- ndmin:指定生成数组的最小维度
2. numpy.empty(shape, dtype = float, order = ‘C’)
numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。
- shape 数组形状
- dtype 数据类型,可选
- order 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
输入:
x = np.empty([2,3], dtype=int)
print(x)
输出:
[[-431684108 2046 -431678912]
[ 2046 655108618 282066943]]
数组元素为随机值,因为它们未初始化。
3. numpy.zeros(shape, dtype = float, order = ‘C’)
创建指定大小的数组,数组元素以 0 来填充
- shape:数组形状
- dtype:数据类型,可选
- order :有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
4. numpy.ones(shape, dtype = float, order = ‘C’)
创建指定大小的数组,数组元素以 1 来填充
- shape:数组形状
- dtype:数据类型,可选
- order :有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
5. numpy.asarray(a, dtype = None, order = None)
- a:任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组
- dtype:数据类型,可选
- order :可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
输入:
x = np.array([1,(2,3)])
print(x)
输出:
[1 (2, 3)]
6. numpy.fromiter(iterable, dtype, count = -1)
numpy.fromiter 方法从可迭代对象中建立 ndarray 对象,返回一维数组。
- iterable:可迭代对象
- dtype:返回数组的数据类型
- count:读取的数据数量,默认为-1,读取所有数据
输入:
it = (x*x for x in range(5))
x = np.fromiter(it, dtype=float, count=-1)
print(x)
输出:
[ 0. 1. 4. 9. 16.]
7. numpy.arange(start, stop, step, dtype)
创建数值范围并返回 ndarray 对象
- start:起始值,默认为0
- stop:终止值(不包含)
- step:步长,默认为1
- dtype:返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。
输入:
x = np.arange(1, 10, 2)
print(x)
输出:
[1 3 5 7 9]
8. numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
创建一个等差数列构成的一维数组
- start:序列的起始值
- stop :序列的终止值,如果endpoint为true,该值包含于数列中
- num:要生成的等步长的样本数量,默认为50
- endpoint:该值为 ture 时,数列中中包含stop值,反之不包含,默认是True。
- retstep:如果为 True 时,生成的数组中会显示间距,反之不显示。
- dtype:ndarray 的数据类型
输入:
x = np.linspace(1, 10, 4, retstep=True)
y = np.linspace(2, 8, 3, endpoint=False)
print(x)
print(y)
输出:
(array([ 1., 4., 7., 10.]), 3.0)
[2. 4. 6.]
9. numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
创建一个等比数列构成的一维数组
- start :序列的起始值为:base ** start (例如start=2, base=9,即为9²)
- stop:序列的终止值为:base ** stop。如果endpoint为true,该值包含于数列中
- num:要生成的等步长的样本数量,默认为50
- endpoint:该值为 ture 时,数列中中包含stop值,反之不包含,默认是True
- base:对数 log 的底数
- dtype:ndarray 的数据类型
输入:
x = np.logspace(1, 4, 4, base=3)
print(x)
输出:
[ 3. 9. 27. 81.]
四、数组索引
1. 基于下标索引
(1)一维数组:
输入:
x = np.arange(10)
print(x)
print(x[2:8:2]) # 从下标2到下标7,步长为2
print(x[3]) # 下标为3的元素
输出:
[0 1 2 3 4 5 6 7 8 9]
[2 4 6]
3
(2)多维数组:
输入:
x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x)
print('\n', x[1:])
输出:
[[1 2 3]
[4 5 6]
[7 8 9]]
[[4 5 6]
[7 8 9]]
还可以使用省略号
输入:
x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x)
print('\n', x[..., 1]) # 第2列元素
print('\n', x[1, ...]) # 第2行元素
print('\n', x[1:, ...]) # 第2行及剩下行的元素
输出:
[[1 2 3]
[4 5 6]
[7 8 9]]
[2 5 8]
[4 5 6]
[[4 5 6]
[7 8 9]]
2. 整数数组索引
输入:
x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x)
print('\n', x[[1, 2], [2, 0]]) # 获取(1,2), (2,0)处的元素
print('\n', x[[[0, 0], [2, 2]], [[0, 2], [0, 2]]]) # 获取(0,0), (0,2), (2,0), (2,2)处的元素
print('\n', x[0:2, 1:]) # 获取1、2行和2、3列交叉处的元素
print('\n', x[1:, [0, 2]]) # 获取2、3行和第1、第3列交叉处的元素
print('\n', x[..., 1:]) # 获取所有行和2、3列交叉处的元素
输出:
[[1 2 3]
[4 5 6]
[7 8 9]]
[6 7]
[[1 3]
[7 9]]
[[2 3]
[5 6]]
[[4 6]
[7 9]]
[[2 3]
[5 6]
[8 9]]
3. 布尔索引
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
输入:
x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x)
print('\n', x[x > 5]) # 选取大于6的元素
print('\n', x[(x < 3) | (x > 8)]) # 选取小于3或大于8的元素,或|, 且&
print('\n', x[x != 5]) # 选取x不等于5的元素
print('\n', x[:, 1][(x[:, 1] > 4) & (x[:, 1] < 8)]) # 第2列大于4且小于8的元素
输出:
[[1 2 3]
[4 5 6]
[7 8 9]]
[6 7 8 9]
[1 2 9]
[1 2 3 4 6 7 8 9]
[5]
4. 花式索引
花式索引指的是利用整数数组进行索引。花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。花式索引跟切片不一样,它总是将数据复制到新数组中。
输入:
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
y = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(y)
print('\n', x[[3, 1, 2]]) # 传入顺序索引数组
print('\n', y[[2, 0, 1]])
print('\n', x[[-1, -3]]) # 传入倒序索引数组
# 传入多个索引数组,需要用np.ix_,此处相当于取(1,2),(1,1),(0,2),(0,1)四个元素
print('\n', y[np.ix_([1, 0], [2, 1])])
输出:
[[1 2 3]
[4 5 6]
[7 8 9]]
[4 2 3]
[[7 8 9]
[1 2 3]
[4 5 6]]
[9 7]
[[6 5]
[3 2]]
五、广播(Broadcast)
如果两个数组的形状相同,即a.shape == b.shape,则 a*b 为a与b对应位置的元素相乘;如果两个数组的形状不同,则形状小的数组在计算时会自动补齐,这就是广播机制。
广播的原则:
- 让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分都通过在前面加1补齐
- 输出数组的shape是输入数组shape的各个轴上的最大值
- 如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错
- 当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值
解析:
若数组a的shape为(3,4,2),数组b的shape为(2,),则由广播第1条原则和第2条原则,有
a 3 × 4 × 2
b 1 × 1 × 2 (第1条原则,输入数组向最长的shape看齐,不足的在前面补1)
result 3 × 4 × 2 (第2条原则,输出数组各轴取输入数组各轴长度的最大值)
第3条原则明确了能否进行广播运算,即,a与result形状完全一样显然可以,b的第0轴和第1轴与输出数组长度不一样,但是为1,则可以进行广播运算。如果是下面这种情况
a 3 × 4 × 2
b 1 × 1 × 3
result 3 × 4 × 3
则a的第2轴为2小于输出数组第2轴的长度3,且不为1,则a不能参与广播运算。这里也可以理解为,当进行运算时,a的第2轴的长度需要扩充为3,但是a在第2轴有两组值,则无法确定到底以哪一组值去扩充,因此第3条规则保证了扩充时不会产生歧义。
第4条原则明确了当输入数组某一轴长度为1需要进行扩充时,用的是此轴上的第1组值,也就是唯一的那组值。
输入:
a = np.array([[[1, 2], [3, 4], [5, 6], [7, 8]],
[[2, 4], [6, 8], [10, 12], [14, 16]],
[[1, 3], [5, 7], [11, 13], [15, 17]]])
b = np.array([2, 4])
print(a + b)
输出:
[[[ 3 6]
[ 5 8]
[ 7 10]
[ 9 12]]
[[ 4 8]
[ 8 12]
[12 16]
[16 20]]
[[ 3 7]
[ 7 11]
[13 17]
[17 21]]]
六、迭代访问数组元素
迭代器对象 numpy.nditer
1. 遍历
输入:
x = np.arange(1, 9).reshape(2, 4)
print(x, '\n')
for i in np.nditer(x, order='C'): # 行序优先,默认值是行序优先
print(i, end=' ')
print('\n')
for i in np.nditer(x, order='F'): # 列序优先
print(i, end=' ')
输出:
[[1 2 3 4]
[5 6 7 8]]
1 2 3 4 5 6 7 8
1 5 2 6 3 7 4 8
2. 修改元素值
nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定 read-write 或者 write-only 的模式。
输入:
x = np.arange(1, 9).reshape(2, 4)
print(x, '\n')
for i in np.nditer(x, op_flags=['readwrite']):
i[...] = i + 3
print(x)
输出:
[[1 2 3 4]
[5 6 7 8]]
[[ 4 5 6 7]
[ 8 9 10 11]]
3. 广播迭代
如果两个数组是可广播的,nditer 组合对象能够同时迭代它们(遵循广播原则)。
输入:
a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
b = np.array([11, 22, 33, 44])
for x,y in np.nditer([a,b]):
print('(%d,%d)' % (x,y), end=' ')
输出:
(1,11) (2,22) (3,33) (4,44) (5,11) (6,22) (7,33) (8,44) (9,11) (10,22) (11,33) (12,44)
七、数组属性
NumPy 数组的维数称为秩(rank)。在 NumPy中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。以一个二维数组为例
[[1,4]
[2,7]]
# 令 a = [1,4], b = [2,7]
这个数组就相当于两个一维数组,第一个一维数组是 [a, b],而第一个一维数组中的每一个元素又是一个一维数组即[1, 4] 和 [2, 7]。因此一维数组就是NumPy中的轴,轴的数量就是数组的维数(维度的数量)也就是秩。
在操作二维数组时,经常会声明axis。axis=0 表示沿第0轴进行操作,即对每一列进行操作;axis=1,表示沿第1轴进行操作,即对每一行进行操作。
1. ndarray.ndim
秩,即轴的数量或维度的数量
2. ndarray.shape
表示数组的维度,返回一个元组,这个元组的长度就是维度的数量。比如对于
x = np.array([[[1],[2],[3]],[[2],[2],[3]]])
print(x.shape)
输出结果
(2,3,1)
这个元组的长度是3,表示x的维数是3。而2、3、1分别表示第一个一维数组的维数是2、第二个一维数组的维数是3、第三个一维数组的维数是1。
3. ndarray.size
数组元素的总个数,即.shape中各个数字相乘,以(2,3,1)为例就是2*3*1=6个。
4. ndarray.dtype
ndarray 对象元素的数据类型。
5. ndarray.itemsize
ndarray 对象中每个元素的大小,以字节为单位。
6. ndarray.real
ndarray元素的实部,如果元素是复数,比如1+3j,则会返回1.
7. ndarray.imag
ndarray元素的虚部,如果元素是复数,比如1+3j,则会返回3.
八、函数
(一) 操作函数
1. 修改形状函数
(1) numpy.reshape(a, newshape, order = ‘C’)
改变数组的形状。
- a:要修改形状的数组
- newshape:整数或者整数数组,新的形状应当兼容原有形状
- order:‘C’ – 按行;‘F’ – 按列;‘A’ – 按存储决定,存储是C就是C,是F就是F。
输入:
x = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(np.reshape(x,(6, 2), order='F'))
输出:
[[ 1 3]
[ 5 7]
[ 9 11]
[ 2 4]
[ 6 8]
[10 12]]
(2) ndarray.flatten(order = ‘C’)
返回一份数组拷贝,展开为一维,对拷贝所做的修改不会影响原始数组。
- order:‘C’ – 按行;‘F’ – 按列;‘A’ – 按存储决定,存储是C就是C,是F就是F;‘K’,按内存中出现的顺序。
输入:
x = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
y = x.flatten(order='F')
y[0] = 999
print(y)
print(x)
输出:
[999 5 9 2 6 10 3 7 11 4 8 12]
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
(3) numpy.ravel(a, order = ‘C’)
将数组展开为一维,对展开的一维数组所做的修改会影响原始数组。
- order:‘C’ – 按行;‘F’ – 按列;‘A’ – 按存储决定,存储是C就是C,是F就是F;‘K’,按内存中出现的顺序。
输入:
x = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
z = np.ravel(x)
z[0] = 999
print(z)
print(x)
输出:
[999 2 3 4 5 6 7 8 9 10 11 12]
[[999 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
2. 翻转数组函数
(1) numpy.transpose(a, axes=None)
对换数组的维度。注意一维数组进行此操作,不会有变化。
- a:要操作的数组。
- axes:整数列表,对应维度,默认所有维度都会对换。
输入:
x = np.arange(4).reshape((2,2))
print(x)
print(np.transpose(x))
输出:
[[0 1]
[2 3]]
[[0 2]
[1 3]]
(2) numpy.swapaxes(a, axis1, axis2)
交换数组的两个轴。
- a:要操作的数组。
- axis1:对应第一个轴的整数。
- axis2:对应第二个轴的整数。
输入:
x = np.arange(1, 13).reshape(2, 3, 2)
print(x, '\n')
print(np.swapaxes(x, 2, 1))
输出:
[[[ 1 2]
[ 3 4]
[ 5 6]]
[[ 7 8]
[ 9 10]
[11 12]]]
交换后
[[[ 1 3 5]
[ 2 4 6]]
[[ 7 9 11]
[ 8 10 12]]]
即原来是 (2,3,2),将第2轴与第1轴交换得到 (2,2,3)
3. 修改维度函数
(1) numpy.broadcast_to(a, shape, subok=False)
将数组广播到新形状。
- a:要广播的数组
- shape:广播后的形状
- subok:默认返回一个与基类类型一致的数组
输入:
x = np.arange(1,6)
print(x, '\n')
print(np.broadcast_to(x,(5,5)))
输出:
[1 2 3 4 5]
[[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]]
(2) numpy.expand_dims(a, axis)
在指定位置插入新的轴。
- a:输入数组
- axis:新轴插入的位置
输入:
x = np.arange(1, 5).reshape(2, 2)
print(x)
print('\n', np.expand_dims(x, 0))
print('\n', np.expand_dims(x, 1))
print('\n', np.expand_dims(x, 2))
输出:
[[1 2]
[3 4]]
[[[1 2]
[3 4]]]
[[[1 2]]
[[3 4]]]
[[[1]
[2]]
[[3]
[4]]]
(3) numpy.squeeze(a, axis=None)
从给定数组的形状中删除一维。
- a:输入数组
- axis:整数或整数元组,用于选择形状中一维条目的子集(注意只有长度为1的轴能选)
输入:
x = np.arange(1, 10).reshape(1, 3, 3)
print(x)
print('\n', np.squeeze(x, 0))
print('\n', np.squeeze(x, 1)) # 第1轴长度为3不为1,故会报错
输出:
[[[1 2 3]
[4 5 6]
[7 8 9]]]
[[1 2 3]
[4 5 6]
[7 8 9]]
ValueError: cannot select an axis to squeeze out which has size not equal to one
4. 连接数组函数
(1) numpy.concatenate((a1, a2, …), axis=0, out=None)
沿指定轴连接相似形状(连接处长度一致)的多个数组。
- a1, a2, …:相同类型的数组
- axis:沿着它连接数组的轴,默认为 0
- out:指定放置结果的地点
输入:
a = np.arange(1,5).reshape(2,2)
b = np.arange(5,7).reshape(2,1)
print(a)
print(b)
print(np.concatenate((a,b), axis=1))
输出:
[[1 2]
[3 4]]
[[5]
[6]]
[[1 2 5]
[3 4 6]]
(2) numpy.stack((a1, a2, …), axis=0, out=None)
沿新轴连接数组序列。
- a1, a2, …:相同类型的数组(必须形状完全相同)
- axis:返回数组中的轴,输入数组沿着它来堆叠
- out:指定放置结果的地点
输入:
a = np.arange(1, 5).reshape(2, 2)
b = np.arange(5, 9).reshape(2, 2)
print(a)
print(b)
print(np.stack((a, b), axis=0))
print(np.stack((a, b), axis=1))
输出:
[[1 2]
[3 4]]
[[5 6]
[7 8]]
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
[[[1 2]
[5 6]]
[[3 4]
[7 8]]]
5. 分割数组函数
(1) numpy.split(a, indices_or_sections, axis=0)
沿特定的轴将数组分割为子数组。
- a:被分割的数组
- indices_or_sections:若是一个整数,就用该数平均切分,若是一个数组,为沿轴切分的位置(左开右闭)。例如 [2, 3] ,对于 axis=0, 则会按a[:2]、a[2:3]、a[3:]分割
- axis:沿着哪个维度进行切向,默认为0
输入:
x = np.arange(1, 9).reshape(4, 2)
print(x)
print('\n', np.split(x, 4))
print('\n', np.split(x, [1, 3]))
输出:
[[1 2]
[3 4]
[5 6]
[7 8]]
[array([[1, 2]]), array([[3, 4]]), array([[5, 6]]), array([[7, 8]])]
[array([[1, 2]]), array([[3, 4],
[5, 6]]), array([[7, 8]])]
6. 添加删除元素函数
(1) numpy.resize(a, newshape)
返回指定大小的新数组,如果新数组大小大于原始大小,则新数组以原数组的副本不断填充。
- a:要修改大小的数组
- newshape:返回数组的新形状
输入:
x = np.arange(1, 7).reshape(2, 3)
print(x)
print('\n', np.resize(x, (3, 2)))
print('\n', np.resize(x, (2, 2)))
print('\n', np.resize(x, (4, 2)))
输出:
[[1 2 3]
[4 5 6]]
[[1 2]
[3 4]
[5 6]]
[[1 2]
[3 4]] # 形状比原始数组小,则只包含了原始数组的一部分
[[1 2]
[3 4]
[5 6]
[1 2]] # 形状比原始数组大,则重复填充
(2) numpy.append(a, values, axis=None)
在数组的末尾添加值。
- a:输入数组
- values:要向数组a添加的值
- axis:默认为 None,此时原数组和添加的值都会变为一维数组再添加。如果指定了添加轴,则values和数组a需要有同样的维数。
输入:
x = np.arange(1, 7).reshape(2, 3)
print(x)
print('\n', np.append(x, [[11,22],[33,44]], axis=1))
print('\n', np.append(x, [[11,22, 33]], axis=0))
print('\n', np.append(x, [[11,22],[33,44]])) # 不指定添加轴时会变成一位数组
print('\n', np.append(x, [1,2], axis=0)) # 指定添加轴时,维数不一样报错
输出:
[[1 2 3]
[4 5 6]]
[[ 1 2 3 11 22]
[ 4 5 6 33 44]]
[[ 1 2 3]
[ 4 5 6]
[11 22 33]]
[ 1 2 3 4 5 6 11 22 33 44]
ValueError: all the input arrays must have same number of dimensions
(3) numpy.insert(a, obj, values, axis=None)
沿给定轴插入值。
- a:输入数组
- obj:插入值的位置
- values:要插入的值
- axis:沿着它插入的轴,如果未提供,则输入数组会被展开
输入:
x = np.arange(1, 7).reshape(2, 3)
print(x)
print('\n', np.insert(x, 1, [[11, 22, 33], [44, 55, 66]], axis=0))
print('\n', np.insert(x, 1, [[11, 22], [44, 55]], axis=1))
print('\n', np.insert(x, [1, 3], [[11, 22], [44, 55]], axis=1)) # 插到2个不同的位置
print('\n', np.insert(x, 4, [11, 22]))
print('\n', np.insert(x, [1, 4], [11, 22]))
输出:
[[1 2 3]
[4 5 6]]
[[ 1 2 3]
[11 22 33]
[44 55 66]
[ 4 5 6]]
[[ 1 11 44 2 3]
[ 4 22 55 5 6]]
[[ 1 11 2 3 22]
[ 4 44 5 6 55]]
[ 1 2 3 4 11 22 5 6]
[ 1 11 2 3 4 22 5 6]
(4) numpy.delete(a, obj, axis=None)
沿给定轴删除值。
- a:输入数组
- obj:删除的位置
- axis:沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开
输入:
x = np.arange(1, 7).reshape(2, 3)
print(x)
print('\n', np.delete(x, 1, axis=0))
print('\n', np.delete(x, 1, axis=1))
print('\n', np.delete(x, 1))
输出:
[[1 2 3]
[4 5 6]]
[[1 2 3]]
[[1 3]
[4 6]]
[1 3 4 5 6]
(5) numpy.unique(a, return_index=False, return_inverse=False, return_counts=False, axis=None)
去除数组中的重复元素。
- a:输入数组,如果不是一维数组则会展开
- return_index:如果为true,返回新列表元素在旧列表中的位置(下标),并以列表形式储
- return_inverse:如果为true,返回旧列表元素在新列表中的位置(下标),并以列表形式储
- return_counts:如果为true,返回去重数组中的元素在原数组中的出现次数
- axis:操作的轴,如果为None,则会展开为一维数组
输入:
x = np.array([[1, 1, 1], [2, 3, 2]])
print(x)
print('\n', np.unique(x))
print('\n', np.unique(x, return_index=True))
print('\n', np.unique(x, return_inverse=True))
print('\n', np.unique(x, return_counts=True))
print('\n', np.unique(x, axis=1))
输出:
[[1 1 1]
[2 3 2]]
[1 2 3]
(array([1, 2, 3]), array([0, 3, 4], dtype=int64))
(array([1, 2, 3]), array([0, 0, 0, 1, 2, 1], dtype=int64))
(array([1, 2, 3]), array([3, 2, 1], dtype=int64))
[[1 1]
[2 3]]
(二) 数学函数
1. 三角函数
sin()、cos()、tan()、arcsin()、arccos()、arctan(),意义同数学符号。
输入:
x = np.array([0, 30, 60, 90])
x = x * np.pi / 180 # 转化为弧度
print(np.sin(x))
print(np.cos(x))
print(np.tan(x))
print(np.degrees(np.arcsin(np.sin(x)))) # 通过degrees将弧度转化为角度
输出:
[0. 0.5 0.8660254 1. ]
[1.00000000e+00 8.66025404e-01 5.00000000e-01 6.12323400e-17]
[0.00000000e+00 5.77350269e-01 1.73205081e+00 1.63312394e+16]
[ 0. 30. 60. 90.]
2. 舍入函数
(1) numpy.around(a, decimals=0, out=None)
返回四舍五入值。
- a: 输入的数组
- decimals: 舍入的小数位数。如果为负,整数将四舍五入到小数点左侧的位置
输入:
x = np.array([11.3, 235.56, 112.31, -23.21, -123.55])
print('\n', np.around(x))
print('\n', np.around(x, decimals=1))
print('\n', np.around(x, decimals=-1))
输出:
[ 11. 236. 112. -23. -124.]
[ 11.3 235.6 112.3 -23.2 -123.6]
[ 10. 240. 110. -20. -120.]
(2) numpy.floor(a)
向下取整。
输入:
x = np.array([11.3, 235.56, 112.31, -23.21, -123.55])
print('\n', np.floor(x))
输出:
[ 11. 235. 112. -24. -124.]
(3) numpy.ceil(a)
向上取整。
输入:
x = np.array([11.3, 235.56, 112.31, -23.21, -123.55])
print('\n', np.ceil(x))
输出:
[ 12. 236. 113. -23. -123.]
3. 运算函数
(1) numpy.add(a, b)、numpy.subtract(a, b)、numpy.multiply(a, b)、numpy.divide(a, b)、numpy.mod(a, b)
加、减、乘、除、余数。
输入:
a = np.array([[1, 3],
[2, 6]])
b = np.array([[5, 10]])
print('\n', np.add(a, b))
print('\n', np.subtract(a, b))
print('\n', np.multiply(a, b))
print('\n', np.divide(a, b))
print('\n', np.mod(a, b))
输出:
[[ 6 13]
[ 7 16]]
[[-4 -7]
[-3 -4]]
[[ 5 30]
[10 60]]
[[0.2 0.3]
[0.4 0.6]]
[[1 3]
[2 6]]
(2) numpy.reciprocal(a)
返回各元素的倒数。
输入:
a = np.array([[1., 3.],
[2., 6.]])
print(np.reciprocal(a))
输出:
[[1. 0.33333333]
[0.5 0.16666667]]
(3) numpy.power(a, b)
将第一个输入数组中的元素作为底数,计算它与第二个输入数组中相应元素的幂。
输入:
a = np.array([[4., 3.],
[2., 6.]])
b = np.array([[2, 3]])
c = np.array([[1, 2],
[3, 4]])
print('\n', np.power(a, 2))
print('\n', np.power(a, b))
print('\n', np.power(a, c)) # 对应位置
输出:
[[16. 9.]
[ 4. 36.]]
[[ 16. 27.]
[ 4. 216.]]
[[ 4. 9.]
[ 8. 1296.]]
4. 统计函数
(1) numpy.amin()、numpy.amax()
沿指定轴的最小值、最大值。
输入:
x= np.array([[1, 9, 8],
[2, 6, 7]])
print('\n', np.amin(x)) # 全局最小值
print('\n', np.amin(x, axis=0))
print('\n', np.amin(x, axis=1))
输出:
1
[1 6 7]
[1 2]
(2) numpy.ptp(a, axis=None)
沿指定轴求极差。
输入:
x= np.array([[1, 9, 8],
[2, 6, 7]])
print('\n', np.ptp(x)) # 全局极差
print('\n', np.ptp(x, axis=0))
print('\n', np.ptp(x, axis=1))
输出:
8
[1 3 1]
[8 5]
(3) numpy.percentile(a, q, axis=None)
沿轴计算百分位数。
- a: 输入数组
- q: 要计算的百分位数,在 0 ~ 100 之间
- axis: 沿着它计算百分位数的轴
输入:
x = np.arange(1, 13).reshape(3, 4)
print(x)
print('\n', np.percentile(x, 50)) # 全局50%分位数
print('\n', np.percentile(x, 50, axis=0))
print('\n', np.percentile(x, 50, axis=1))
输出:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
6.5
[5. 6. 7. 8.]
[ 2.5 6.5 10.5]
(4) numpy.median(a, axis=None)
沿轴计算中位数。
输入:
x = np.array([[1, 3, 4],
[2, 5, 6]])
print('\n', np.median(x)) # 全局中位数
print('\n', np.median(x, axis=0))
print('\n', np.median(x, axis=1))
输出:
3.5
[1.5 4. 5. ]
[3. 5.]
(5) numpy.mean(a, axis=None, dtype=None)
沿轴计算算术平均数。
输入:
x = np.array([[1, 3, 4],
[2, 5, 6]])
print('\n', np.mean(x)) # 全局算术平均数
print('\n', np.mean(x, dtype=int))
print('\n', np.mean(x, axis=0))
print('\n', np.mean(x, axis=1))
输出:
3.5
3
[1.5 4. 5. ]
[2.66666667 4.33333333]
(6) numpy.average(a, axis=None, weights=None)
沿轴计算加权平均数。
输入:
x = np.array([[1, 3, 4],
[2, 5, 6]])
w = [1, 4, 3] # 权重
print('\n', np.average(x, axis=1, weights=w))
输出:
[3.125 5. ]
(7) numpy.std(a, axis=None, dtype=None)
沿轴计算标准差。
输入:
x = np.array([[1, 3, 4],
[2, 5, 6]])
print('\n', np.std(x))
print('\n', np.std(x, axis=0))
print('\n', np.std(x, axis=1))
输出:
1.707825127659933
[0.5 1. 1. ]
[1.24721913 1.69967317]
(8) numpy.var(a, axis=None, dtype=None)
沿轴计算方差。
5. 排序筛选函数
(1) numpy.sort(a, axis=-1, kind=None, order=None)
返回将数组排序后的副本。
- a: 要排序的数组
- axis: 排序的轴,沿该轴进行排序。如果为None,数组会被展开。默认为-1即沿着最后的轴排序
- kind: 排序算法。可选有’quicksort’(默认)、‘mergesort’、‘heapsort’、‘stable’。具体差别如下
- order: 如果数组包含字段,则是要排序的字段
输入:
x = np.array([[1, 7, 5],
[8, 2, 4]])
print('\n', np.sort(x))
print('\n', np.sort(x, axis=0))
print('\n', np.sort(x, axis=1))
输出:
[[1 5 7]
[2 4 8]]
[[1 2 4]
[8 7 5]]
[[1 5 7]
[2 4 8]]
(2) numpy.argsort(a, axis=-1, kind=None, order=None)
返回数组值从小到大的索引值。
输入:
x = np.array([[1, 7, 5],
[8, 2, 4]])
print('\n', np.argsort(x))
print('\n', np.argsort(x, axis=0))
print('\n', np.argsort(x, axis=1))
输出:
[[0 2 1]
[1 2 0]]
[[0 1 1]
[1 0 0]]
[[0 2 1]
[1 2 0]]
(3) numpy.argmax(a, axis=None)
沿给定轴返回最大元素的索引。
输入:
x = np.array([[1, 7, 5],
[8, 2, 4]])
print('\n', np.argmax(x))
print('\n', np.argmax(x, axis=0))
print('\n', np.argmax(x, axis=1))
输出:
3
[1 0 0]
[1 0]
(4) numpy.argmin(a, axis=None)
沿给定轴返回最小元素的索引。
(5) numpy.nonzero(a)
返回非零元素的索引。
输入:
x = np.array([[1, 3, 0],
[0, 2, 0]])
print(np.nonzero(x))
输出:
(array([0, 0, 1], dtype=int64), array([0, 1, 1], dtype=int64))
即有3个非零元素,分别是(0, 0), (0, 1), (1, 1)
(6) numpy.where(condition[, x, y])
根据条件返回从x或y中选择的元素。
- condition:条件为真时返回x,为假时返回y
- x, y:根据条件选择的返回值,x, y和condition需要广播到相同形状
输入:
x = np.array([[1, 6, 0],
[0, 2, 7]])
print(np.where(x > 5, x, [[11, 22, 33],
[44, 55, 66]])) # 条件、x、y需要同样的形状
输出:
[[11 6 33]
[44 55 7]]
(7) numpy.extract(condition, a)
返回数组中满足条件的元素。如果condition是布尔值,则等同于 a[condition]。
输入:
x = np.array([[1, 6, 0],
[0, 2, 7]])
print(np.extract(x < 5, x))
print(x[x < 5])
输出:
[1 0 0 2]
[1 0 0 2]
6. 矩阵函数
矩阵都是二维的。
(1) numpy.matlib.empty(shape, dtype=None, order=‘C’)
按指定形状返回一个未初始化的矩阵。
- shape: 定义新矩阵形状的整数或整数元组
- dtype: 可选,数据类型
- order: C(行序优先) 或者 F(列序优先),内部存储中的方式
输入:
import numpy as np
import numpy.matlib # 导入矩阵库
x = np.matlib.empty((3, 2))
print(x)
输出:
[[3.46e-322 0.00e+000]
[0.00e+000 0.00e+000]
[0.00e+000 0.00e+000]]
(2) numpy.matlib.zeros(shape, dtype=None, order=‘C’)
按指定形状返回一个以0填充的矩阵。
- shape: 矩阵形状的整数或整数元组
- dtype: 可选,数据类型
- order: C(行序优先) 或者 F(列序优先),内部存储中的方式
输入:
x = np.matlib.zeros((3, 2))
print(x)
输出:
[[0. 0.]
[0. 0.]
[0. 0.]]
(3) numpy.matlib.ones(shape, dtype=None, order=‘C’)
按指定形状返回一个以1填充的矩阵。
- shape: 矩阵形状的整数或整数元组
- dtype: 可选,数据类型
- order: C(行序优先) 或者 F(列序优先),内部存储中的方式
输入:
x = np.matlib.ones((3, 2))
print(x)
输出:
[[1. 1.]
[1. 1.]
[1. 1.]]
(4) numpy.matlib.eye(n, M=None, k=0, dtype=<class ‘float’>, order=‘C’)
按指定形状返回一个对角线为1,其余位置为0的矩阵。
- n: 返回矩阵的行数
- M: 返回矩阵的列数,默认为 n
- k: 对角线的索引,0表示主对角线,正数表示主对角线上方,负数表示主对角线下方。默认为0
- dtype: 数据类型
- order: C(行序优先) 或者 F(列序优先),内部存储中的方式
输入:
a = np.matlib.eye(3)
b = np.matlib.eye(4, 4, k=2)
c = np.matlib.eye(4, 4, k=-3, dtype=int)
print(a, '\n')
print(b, '\n')
print(c, '\n')
输出:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
[[0. 0. 1. 0.]
[0. 0. 0. 1.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0 0 0 0]
[0 0 0 0]
[0 0 0 0]
[1 0 0 0]]
(5) numpy.matlib.identity(n, dtype=None)
按指定形状返回一个单位矩阵。
输入:
x = np.matlib.identity(4)
print(x)
输出:
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
(6) numpy.matlib.rand(*args)
按指定形状返回一个随机生成的矩阵。
输入:
x = np.matlib.rand(2)
y = np.matlib.rand((2, 3))
z = np.matlib.rand(2, 3)
print(x)
print(y)
print(z)
输出:
[[0.26008009 0.91351775]]
[[0.21154435 0.38048646 0.66658642]
[0.02031051 0.59234026 0.50102414]]
[[0.19625724 0.97634868 0.71983559]
[0.02802198 0.79263937 0.66640955]]
7. 线性代数函数
(1) numpy.dot(a, b)
计算两个数组的点积。特别的
- 如果a和b都是一维数组,则结果就是向量的内积(对应下标元素的乘积之和)
- 如果a和b都是二维数组,则结果就是矩阵乘法。此时推荐使用numpy.matmul 或 a @ b
- 如果a或者b是标量,则结果相当于乘法。此时推荐使用numpy.multiply 或 a*b
- 如果a是N维数组,b是1维数组,则结果是沿a和b的最后一个轴乘积的和
- 如果a是N维数组,b是M维数组(M>=2),则结果是沿a的最后一个轴和b的倒数第2个轴的乘积的和
输入:
a = np.array([1, 3, 4])
b = np.array([2, 3, 6])
print('a和b都是1维:\n', np.dot(a, b))
a = np.array([[2, 3], [4, 5]])
b = np.array([[4, 1], [2, 3]])
print('\na和b都是2维:\n', np.dot(a, b))
print(a @ b)
a = np.array([[2, 3], [4, 5]])
b = 3
print('\na或b是标量:\n', np.dot(a, b))
print(np.dot(3, 4))
a = np.array([[2, 3], [4, 5]])
b = np.array([2, 3])
print('\na是n维数组,b是1维数组:\n', np.dot(a, b))
a = np.array([[[2, 3], [4, 5]],
[[1, 2], [5, 2]]])
b = np.array([[2, 1], [3, 5]])
print('\na是n维数组,b是m维数组:\n', np.dot(a, b))
``
输出:
```python
a和b都是1维:
35
a和b都是2维:
[[14 11]
[26 19]]
[[14 11]
[26 19]]
a或b是标量:
[[ 6 9]
[12 15]]
12
a是n维数组,b是1维数组:
[13 23]
a是n维数组,b是m维数组:
[[[13 17]
[23 29]]
[[ 8 11]
[16 15]]]
关于最后一种情况,解释如下:
22+33=13,21+35=17,42+35=23,…
(2) numpy.vdot(a, b)
计算两个向量的点积。跟numpy.dot不一样的是,如果是多维数组会先展开为一维数组,再计算点积(对应元素的乘积之和)。
输入:
a = np.array([[2, 3], [4, 5]])
b = np.array([[4, 1], [2, 3]])
print(np.vdot(a, b))
print(2 * 4 + 3 * 1 + 4 * 2 + 5 * 3)
输出:
34
34
(3) numpy.inner(a, b)
计算两个数组的内积。如果是多维数组,返回最后一个轴上的乘积之和。
输入:
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([[2, 3], [4, 5]])
d = np.array([[4, 1], [2, 3]])
print(np.inner(a, b))
print(np.inner(c, d))
输出:
32
[[11 13]
[21 23]]
多维数组的解释如下:
24+31=11,22+33=13,44+51=21,42+53=23
(4) numpy.matmul(a, b)
计算两个数组的矩阵乘积。
- 如果a和b都是2维数组,则就是正常的矩阵乘法
- 如果a、b中有1个大于2维,则将维数小的数组分别与大于2维数组的最后两轴的元素进行矩阵乘法
输入:
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
print('\n2维乘2维:\n', np.matmul(a, b))
a = np.array([[1, 2], [3, 4]])
b = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print('\n其中一个数组大于2维:\n', np.matmul(a, b))
a = np.array([1, 2])
b = np.array([[5, 6], [7, 8]])
print('\n第1个数组为1维:\n', np.matmul(a, b))
print('\n第2个数组为1维:\n', np.matmul(b, a))
输出:
2维乘2维:
[[19 22]
[43 50]]
其中一个数组大于2维:
[[[ 7 10]
[15 22]]
[[19 22]
[43 50]]]
第1个数组为1维:
[19 22]
第2个数组为1维:
[17 23]
(5) numpy.linalg.det(a)
计算矩阵的行列式。
输入:
x = np.array([[1, 2], [3, 4]])
print(np.linalg.det(x))
输出:
-2.0000000000000004
(6) numpy.linalg.solve(a, b)
返回矩阵形式的线性方程组 aX=b 的解。根据线性代数的知识,系数矩阵必为方阵,当且仅当系数矩阵a的秩等于增广矩阵[a|b]的秩等于未知数个数时,方程有唯一解,即R(a)=R(a|b)=n。如果矩阵不满秩,则会报错。
输入:
a = np.array([[1, 2], [3, 4]])
b = np.array([3, 7])
print(np.linalg.solve(a, b))
a1 = np.array([[1, 2], [2, 4]])
b1 = np.array([3, 7])
print(np.linalg.solve(a1, b1))
输出:
[1. 1.]
numpy.linalg.LinAlgError: Singular matrix # 提示系数矩阵是奇异矩阵
(7) numpy.linalg.inv(a)
返回矩阵的逆矩阵。显然矩阵A必须可逆,即A的行列式不能为0,否则会报错提示矩阵是奇异矩阵。
输入:
x = np.array([[1, 2], [3, 4]])
print(np.linalg.inv(x))
输出:
[[-2. 1. ]
[ 1.5 -0.5]]
(三) IO函数
Numpy 可以读写磁盘上的文本数据或二进制数据。NumPy存储的文件格式为.npy。
(1) numpy.save(file, a, allow_pickle=True, fix_imports=True)
保存数组到以 npz 为扩展名的文件中。
- file:要保存的文件,扩展名为 .npy,如果文件路径末尾没有扩展名 .npy,该扩展名会被自动加上。
- a: 要保存的数组
- allow_pickle: 可选,布尔值,允许使用 Python pickles 保存对象数组,Python 中的 pickle 用于在保存到磁盘文件或从磁盘文件读取之前,对对象进行序列化和反序列化。
- fix_imports: 可选,为了方便 Pyhton2 中读取 Python3 保存的数据。
(2) numpy.savez(file, *args, **kwds)
将多个数组保存到以 npz 为扩展名的文件中。
- file:要保存的文件,扩展名为 .npz,如果文件路径末尾没有扩展名 .npz,该扩展名会被自动加上。
- args: 要保存的数组,可以使用关键字参数为数组起一个名字,非关键字参数传递的数组会自动起名为 arr_0, arr_1, … 。
- kwds: 要保存的数组使用关键字名称。
输入:
x = np.array([[1, 2], [3, 4]])
y = np.array([[1, 3], [3, 4]])
np.savez(r'C:\Users\Administrator\Desktop\test.npz', a=x, b=y) # 使用kwds
npzfile = np.load(r'C:\Users\Administrator\Desktop\test.npz')
print(npzfile.files)
print(npzfile['a'])
输出:
['a', 'b']
[[1 2]
[3 4]]
(3) numpy.load()
读取npy或npz文件。
(4) numpy.savetxt(fname, X, fmt=’%.18e’, delimiter=’ ‘, newline=‘n’, header=’’, footer=’’, comments=’# ', encoding=None)
保存为txt文件。
(5) numpy.loadtxt(fname, dtype=<class ‘float’>, comments=’#’, delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding=‘bytes’, max_rows=None)
从txt文件读取。
参考文献:
[1] https://www.runoob.com/numpy/numpy-tutorial.html
[2] https://www.numpy.org/devdocs/genindex.html#U