除了前面提到的,NumPy还提供了大量对数组进行处理的函数。接下来会对一些常用的函数进行介绍。
一、随机数
函数名 | 功能 | 函数名 | 功能 |
---|---|---|---|
rand | 0到1之间的随机数 | randn | 标准正态分布的随机数 |
randint | 指定范围内的随机数 | normal | 正态分布 |
uniform | 均匀分布 | poisson | 泊松分布 |
permutation | 随机排列 | shuffle | 随机打乱顺序 |
choice | 随机抽取样本 | seed | 设置随机种子 |
- rand()
产生0到1之间的随机浮点数,它的所有参数用于指定所产生的数组的形状 - randn()
产生标准正态分布的随机数,参数含义同rand()
- randint()
产生指定范围内的随机整数,包括起始值,但是不包括终值
from numpy import random as nr
np.set_printoptions(precision=2) # 只显示小数点后两位数字
r1 = nr.rand(4, 3)
r2 = nr.randn(4, 3)
r3 = nr.randint(0, 10, (4, 3))
print(r1)
print('-'*20)
print(r2)
print('-'*20)
print(r3)
- normal()
正态分布,前两个参数分别为期望值和标准差 - uniform()
均匀分布,前两个参数分别为区间的起始值和终值 - poisson()
泊松分布,第一个参数指定 λ \lambda λ系数,它表示单位时间(或面积)内随机事件的平均发生率。由于泊松分布是一个离散分布,因此输出是一个整数数组
from numpy import random as nr
np.set_printoptions(precision=2) # 只显示小数点后两位数字
r1 = nr.normal(100, 10, (4, 3))
r2 = nr.uniform(10, 20, (4, 3))
r3 = nr.poisson(2.0, (4, 3))
print(r1)
print('-'*20)
print(r2)
print('-'*20)
print(r3)
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 | 求和 | mean | 期望 |
average | 加权平均数 | std | 标准差 |
var | 方差 | product | 连乘积 |
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 | 最大值 |
minimum | 二元最小值 | maximum | 二元最大值 |
ptp | 最大值与最小值的差 | argmin | 最小值的下标 |
argmax | 最大值的下标 | unravel_index | 一维下标转换成多维下标 |
sort | 数组排序 | argsort | 计算数组排序的下标 |
lexsort | 多列排序 | partition | 快速计算前k位 |
argpartition | 前k位的下标 | median | 中位数 |
percentile | 百分位 | searchsorted | 二分查找 |
用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默认值为1
argsort()
返回数组的排序下标,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 | 去除重复元素 | bincount | 对整数数组的元素记数 |
histogram | 一维直方图统计 | digitze | 离散化 |
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.6
histogram()
对一维数组进行直方图统计。
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 | 连接多个数组 | vstack | 沿第0轴连接数组 |
hstack | 沿第1轴连接数组 | column_stack | 按列连接多个一维数组 |
split、array_split | 将数组分为多段 | transpose | 重新设置轴的顺序 |
swapaxes | 交换两个轴的顺序 |
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))
由于数组太长了,就注释掉了。
六、各种乘积运算
函数名 | 功能 | 函数名 | 功能 |
---|---|---|---|
dot | 矩阵乘积 | inner | 内积 |
outter | 外积 | tensordot | 张量乘积 |
由于对矩阵乘积运算不太熟悉。。。。就只提下有哪些功能hhhh