除了前面提到的,NumPy还提供了大量对数组进行处理的函数。接下来会对一些常用的函数进行介绍。
permutation()用于产生一个乱序数组。 当参数为整数n时,返回[0,n)这n个整数的随机排列 当参数为一个序列时,返回一个随机排列之后的序列
from numpy import random as nr a = np.array([1, 10, 20, 30, 40]) print(nr.permutation(10)) print('-'*20) print(nr.permutation(a))permutation()返回的是一个新数组,而shuffle()是将原数组的顺序打乱
from numpy import random as nr a = np.array([1, 10, 20, 30, 40]) print(a) print('-'*20) nr.shuffle(a) print(a)choice()从指定的样本中随机进行抽取:
size size参数用于指定输出数组的形状replace replace参数为False时,不重复抽取,默认为True。p p参数指定每个元素对应的额抽取概率。若不指定,则每个元素被抽取到的额概率相同 from numpy import random as nr a = np.arange(10, 25, dtype=float) c1 = nr.choice(a, size=(4, 3)) c2 = nr.choice(a, size=(4, 3), replace=False) c3 = nr.choice(a, size=(4, 3), p=a / np.sum(a)) print(c1) print('-'*20) print(c2) print('-'*20) print(c3)seed()用于设置伪随机种子,即每次运行时能重现相同的随机数
from numpy import random as nr r1 = nr.randint(0, 100, 3) r2 = nr.randint(0, 100, 3) nr.seed(42) r3 = nr.randint(0, 100, 3) nr.seed(42) r4 = nr.randint(0, 100, 3) print(r1) print('-'*20) print(r2) print('-'*20) print(r3) print('-'*20) print(r4)sum()计算数组元素之和,也可以对列表、元组等与数组类似的序列进行求和。 当数组是多维时,它计算数组中所有元素的和
import numpy as np np.random.seed(42) a = np.random.randint(0,10,size=(4,5)) print(a) print('-'*20) print(np.sum(a))如果指定axis参数,则会对指定的轴进行求和
import numpy as np np.random.seed(42) a = np.random.randint(0,10,size=(4,5)) print(a) print('-'*20) print(np.sum(a, axis=0)) # 对每列求和,共5列,即[6+3+9+3+4, 3+2+7+1, 7+6+7+7, 4+7+2+5, 6+4+5+1] print('-'*20) print(np.sum(a, axis=1)) # 对每行求和,共4行当axis的值是一个轴的序列时,则对指定的所有轴进行求和
b = np.array([[[1,1,1],[2,2,2]], [[3,3,3], [4,4,4]]]) print(b.shape) print('-'*20) print(b) print('-'*20) print(np.sum(b, axis=(1,2))) print('-'*20) print(np.sum(b, axis=(0,2)))mean()是求数组的平均值。参数与sum()是相同的。
a = np.random.randint(0,10,size=(4,5)) print(a) print('-'*20) print(np.mean(a, axis = 0))除了mean(),average()也可以对数组进行平均计算
相比于mean(),average()可以计算加权平均数
score = np.array([83, 72, 79]) # 三个班级 number = np.array([20, 15, 30]) # 每个班级的人数 print(np.average(score, weights=number)) # 整个年级的平均分std()和var()分别计算数组的标准差和方差 有axis、out、dtype以及keepdims等参数
其中方差有两种定义: (1)偏样本方差
s n 2 = 1 n ∑ i = 1 n ( y i − y ˉ ) 2 s_{n}^{2}=\frac{1}{n}\sum_{i=1}^{n}(y_{i}-\bar{y})^2 sn2=n1∑i=1n(yi−yˉ)2
(2)无偏样本方差
s 2 = 1 n − 1 ∑ i = 1 n ( y i − y ˉ ) 2 s^{2}=\frac{1}{n-1}\sum_{i=1}^{n}(y_{i}-\bar{y})^2 s2=n−11∑i=1n(yi−yˉ)2
当ddof为0时,计算篇样本方差,且可省略;ddof为1时,计算无偏样本方差 默认为0
import numpy as np from numpy import random as nr a = nr.normal(0, 2.0, (100000, 10)) # 产生一个标注差为2.0,方差为4.0的正态分布的随机数组 v1 = np.var(a, axis=1, ddof=0) # 可以省略ddof=0 v2 = np.var(a, axis=1, ddof=1) print(np.mean(v1)) print('-'*20) print(np.mean(v2))可以看出无偏样本方差的期望更接近于4,0
用min()和max()可以计算数组的最小值和最大值,且都有axis、out、keepdims等参数
ptp()计算最大值和最小值之间的差,有axis和out参数
minimum()和maximum()用于比较两个数组对应下标的元素,返回数组的形状为两参数数组广播之后的形状
a = np.array([1, 3, 5, 7]) b = np.array([2, 4, 6]) print(np.max(a)) print('-'*20) print(np.min(b)) print('-'*20) print(np.ptp(a)) print('-'*20) # 7-1=6 print(np.maximum(a[None, :], b[:, None]))用argmax()和argmin()可以求最大值和最小值的下标。 若存在多个最值,则返回第一个最值的下标
np.random.seed(42) a = np.random.randint(0, 10, size=(4, 5)) print(a) print('-'*20) max_pos = np.argmax(a) print(max_pos)通过unravel_index()将一维数组的下标转换成多维数组的下标。
第一个参数为一维数组的下标,第二个参数是多维数组的形状
a = np.random.randint(0, 10, size=(4, 5)) print(a) print('-'*20) idx = np.unravel_index(max_pos, a.shape) print(idx) print('-'*20) print(a[idx])sort()函数对数组进行排序,且改变数组的内容,但不改变原数组 可以通过修改axis的值来选择排序的轴
a = np.random.randint(0, 10, size=(4, 5)) print(a) print('-'*20) print(np.sort(a, axis = 0)) print('-'*20) print(np.sort(a)) # axis默认值为1argsort()返回数组的排序下标,axis默认值同为-1
a = np.random.randint(0, 10, size=(4, 5)) print(a) print('-'*20) sort_axis0 = np.argsort(a, axis=0) sort_axis1 = np.argsort(a) print(sort_axis0) print('-'*20) print(sort_axis1)lexsort()类似于Excel中的多列排序。参数是一个形状为(k, N)的数组,或者包含k个长度为N的数组的序列。 lexsort()返回的是排序下标
names = ["zhang", "wang", "li", "wang", "zhang"] ages = [37, 33, 32, 31, 36] idx = np.lexsort([ages, names]) print(idx)partition()和argpartition()对数组进行分割,可以很快的找出排序后的前k个元素 本质和sort()类似,不过比其速度要快很多
r = np.random.randint(10, 1000000, 100000) print(np.sort(np.partition(r, 5)[:5]))median()可以获得数组的中值 若长度为偶数,则得到中间两个数的平均值,也可以指定axis和out参数
a = np.random.randint(0, 10, size=(4, 5)) print(a) print('-'*20) print(np.median(a, axis=0)) print('-'*20) print(np.median(a, axis=1))percentitle()用于计算百分位数,即将数值从小到大排列,计算处于p%位置上的值
r = np.abs(np.random.randn(100000)) print(np.percentile(r, [68.3, 95.4, 99.7]))searchsorted()用于二分搜索,前提是数组中的元素按照从小到大的顺序已经排列好
a = [2, 4, 8, 16, 16, 32] v = [1, 5, 33, 16] print(np.searchsorted(a, v))a是一个已经排列好的列表,v是需要搜索的数值列表。searchsorted()返回一个下标数组,将v中对应的元素插入到a中的位置,保持数据的升序排列。
unique()返回参数数组中所有不同的值,并且按从小到大的顺序排列。
它有两个可选参数:
return_index:Ture表示同时返回原始数组的下标return_inverse:True表示返回重建原始数组用的下标数组 np.random.seed(42) a = np.random.randint(0, 8, 10) print(a) print('-'*20) print(np.unique(a)) print('-'*20) b = np.unique(a, return_index = True) print(b) print('-'*20) c = np.unique(a, return_inverse = True) print(c)print(b)返回的是第一个array是unique()后的array,第二个array是unique()后的array中的元素,在原array也就是a中的位置。如unique()后的array的第一个元素1,在a中的位置为9,故返回的第二个array中第一个元素为9
print(c)返回的是原array即a中的元素,在unique()后中array中的位置。
bincount()对整数数组中各个元素所出现的次数进行统计,它要求数组中的而所有元素都是非负的。
np.random.seed(42) a = np.random.randint(0, 8, 10) print(a) print('-'*20) b = np.bincount(a) print(b)print后返回的7个col分别代表0-6,0出现的次数为0,1出现的次数为1…以此类推
还可以通过weights参数指定每个数对应的权值
x = np.array([0 , 1, 2, 2, 1, 1, 0]) w = np.array([0.1, 0.3, 0.2, 0.4, 0.5, 0.8, 1.2]) print(np.bincount(x, w))返回的分别是x中对应的元素在w中的值的和
即
0:0.1+1.2 = 1.3 1:0.3+0.5+0.8 = 1.6 2:0.2+0.4 = 0.6histogram()对一维数组进行直方图统计。
histogram(a, bins=10, range=None, weights=None, density=False)
a是保存待统计数据的数组
bins指定统计的区间个数
range是一个长度为2的元组,表示统计范围的最小值和最大值。默认值为None,表示范围由数组的范围决定,即(a.min(), a.max())
density为False时,返回a中的数据在每个区间的个数,为True则返回每个区间的概率密度,
weights和bincount()类似
a = np.random.rand(100) b = (np.histogram(a, bins=5, range=(0, 1))) print(b)histogram()后会返回两个数组hist和bin_edges
hist是每个区间的统计结果,bin_edges的长度为len(hist)+1每两个相邻的数值构成一个统计区间。
根据上例: 生成的a是100个取值为0-1的随机array。 可以看出: 28个元素的值在0-0.2之间; 18个元素的值在0.2-0.4之间… 以此类推
还可以通过bins指定区间分割位置
print(np.histogram(a, bins=[0, 0.4, 0.8, 1.0]))即46个元素的值在0-0.4之间…
concatenate()是连续多个数组的最基本的函数,其他函数都是它的快捷版本。 它的第一个参数是包含多个数组的序列,它将沿着axis参数指定的轴(默认为0)连接数组。
a = np.arange(6).reshape(2,3) b = np.array([[7,8,9], [10,11,12]]) print(a) print('-'*20) print(b) print('-'*20) print(np.concatenate((a,b))) print('-'*20) print('设定按第0轴\n') print(np.concatenate((a,b), axis = 0)) print('-'*20) print('设定按第1轴\n') print(np.concatenate((a,b), axis = 1))vstack()沿着第0轴连接数组,当被连接的数组是长度为N的一维数组时,将其形状改为(1, N) hstack()沿着第1轴连接数组,当所有数组都是一维时,沿着第0轴连接数组。 其实vstack()和hstack()可以直接理解为分别对应concatenate((a,b), axis = 0)和concatenate((a,b), axis = 1)
除了vstack()和hstack(),还有stack() stack()不同于vstack和hstack,可以理解为,vstack和hstack是矩阵的连接,而stack()是矩阵的堆积。 两个二维的矩阵,vstack和hstack后还是二维的,而stack后是三维的。
stack()同样可以设置axis参数
a = np.arange(0, 8).reshape(2,4) b = np.arange(8, 16).reshape(2,4) c = np.arange(16, 24).reshape(2,4) print(a) print('-'*20) print(b) print(''*20) print('*'*10 + '开始堆叠' + '*'*10) print(''*20) s0 = np.stack((a,b), axis = 0) print(s0) print('-'*20) print('s0的shape:',s0.shape) print('-'*20) s1= np.stack((a,b), axis = 1) print(s1) print('-'*20) print('s1的shape:',s1.shape) print('-'*20) s2= np.stack((a,b), axis = 2) print(s2) print('-'*20) print('s2的shape:',s2.shape)堆积的过程可能比较难理解。但首先可以很直观的看出来,stack后的矩阵都是三维的。
当axis=0时,仅仅是“单纯”的堆起来。 当axis=1时,可以理解为是二维数组时axis=0的处理过程 当axis=2时,可以理解为是二维数组时axis=1的处理过程
显然,如果axis=2,堆积后的shape应该是(2, 1, 8)。这时可以理解为,就数组的shape来说,axis=2是axis=1时的转置。而axis=1的shape和axis=0时是一样的。
这样,为了使axis=2的shape为(2, 4, 2),因此要使每个矩阵再转置一次,就成了最后的结果。
听起来非常非常复杂。。。多换几个shape的数组,例如换成(2,3)的数组堆积,不嫌麻烦甚至可以换成(2, 5)的数组,再分别用axis=0、axis=1、axis=2堆积,就可以大致懂了
column_stack()和hstack()类似,沿着第1轴连接数组,但是当数组为一维时,将其形状改为(N, 1),经常用于按列连接多个一维数组。
a = np.arange(3) b = np.arange(10, 13) print(a) print('-'*20) print(b) print('-'*20) c = np.column_stack((a, b)) print(c)除了上述这些,c_[]对象也可以用于按列连接数组
a = np.arange(3) b = np.arange(10, 13) c = np.c_[a, b, a+b] print(c)split()和array_split()的用法基本相同,将一个数组沿着指定轴分成多个数组,可以直接指定切分轴上的切分点下标
np.random.seed(42) a = np.random.randint(0, 10, 12) print(np.split(a, 6)) print('-'*20) print(np.array_split(a, 5))transpose()和swapaxes()用于修改轴的顺序,它们得到的是原数组的视图。 transpose()通过其第二个参数axes指定轴的顺序,默认将整个形状翻转。 swapaxes()通过两个整数指定调换顺序的轴
a = np.random.randint(0, 10, (2, 3, 4, 5)) print("原数组形状:", a.shape) # print('') # print(a) print('*'*20) print("transpose:", np.transpose(a, (1, 2, 0, 3)).shape) # print('') # print(np.transpose(a, (1, 2, 0, 3))) print('*'*20) print("swapaxes:", np.swapaxes(a, 1, 2).shape) # print('') # print(np.swapaxes(a, 1, 2))由于数组太长了,就注释掉了。
由于对矩阵乘积运算不太熟悉。。。。就只提下有哪些功能hhhh