Python NumPy库 常见基本用法总结(学习笔记)
目录
简介
1.ndarray对象
1.1 创建数组
1.1.1 np.array()
1.2 数组形状与元素类型
1.2.1 ndarray.shape #获得形状
1.2.2 ndarray.reshape() #改变形状
1.2.3 ndarray.dtype #获得元素类型
1.2.4 ndarray.astype() #转换元素类型
1.2.5 np.set_printoptions(precision = ) #控制小数点位数
1.3 自动生成数组
1.3.1 np.arange() #等差一维数组
1.3.2 np.linspace() #等差一维数组
1.3.3 np.logspace() #指数数组
1.3.4 np.zeros()、np.ones()、np.empty()、np.full() #特殊数组
1.3.5 np.zeros_like()、np.ones_like()、np.empty_like()、np.full_like() #形状相同的特殊数组
1.4 存取元素
1.4.1 下标、切片
1.4.2 ndarray[[ ]] #批量提取数组元素
1.4.3 ndarray.take() #获取元素
1.4.3 np.compress() #通过布尔数组获取元素
1.5 多维数组
1.5.1 二维数组的创建
1.5.2 二维数组的切片
1.6 结构数组
1.6.1 定义结构数组 np.dtype()
1.6.2 结构数组的存取
2.ufunc对象
2.1 四则运算
2.2 比较运算和布尔运算
2.2.1 比较运算(<,=,>)
2.2.2 布尔运算(np.logical_and、or、not)
2.2.3 布尔运算(np.all()、np.any())
2.3 自定义ufunc函数
2.3.1 np.frompyfunc() #分段函数
2.4 广播(broadcasting)
2.4.1 广播处理规则
2.4.2 np.broadcast_arrays() #查看广播之后的数组
2.4.3 ndarray.repeat() #复制元素
2.4.4 下标对象None
2.5 ufunc的方法
2.5.1 np..reduce() #对数组内元素四则运算
2.5.2 np..accumulate() #对数组内元素四则运算
2.5.3 np..reduceat() 计算多组reduce()的结果
2.5.4 np..outer() #计算表
3.多维数组的下标存取
3.1 下标对象
3.2 整数数组作为下标
3.3 布尔数组作为下标
3.3.1 np.nonzero() #找出不为0的元素
4.NumPy的函数库
4.1 随机数(np.random模块)
4.1.1 np.random.rand()(产生随机0~1浮点数)
4.1.2 np.random.randn()(产生正态分布随机数)
4.1.3 np.random.randint()(产生随机整数)
4.1.4 np.random.normal()(随正态分布)
4.1.5 np.random.uniform()(均匀分布)
4.1.6 np.random.possion()(泊松分布)
4.1.7 np.random.permutation() #产生乱序数组、打乱数组
4.1.8 np.random.shuffle() #打乱数组
4.1.9 np.random.choice() #随机抽取
4.1.10 np.random.seed() #种子
4.2 求和、平均值、方差
4.2.1 np.sum() #求和
4.2.2 np.mean() #求平均数
4.2.3 np.average() #计算加权平均数
4.2.4 np.std() #计算标准差
4.2.5 np.var() #计算方差
4.2.6 np.product() #计算所有元素乘积
4.3 大小与排序
4.3.1 np.min(),np.max(),np.minimum(),np.maximum(),np.ptp()
4.3.2 np.argmax(),np.argmin() #求最值下标
4.3.3 np.unravel_index() #下标转化
4.3.4 np.sort() #排序
4.3.5 np.argsort() #排序后的下标
4.3.6 np.lexsort() #多列排序
4.3.6 np.lexsort() 应用:成绩姓名全局排序
4.3.7 np.partition(),np.argpartition() #数组分割
4.3.8 np.median() #计算中位数
4.3.9 np.percentile() #计算百分数
4.3.10 np.searchsorted() #插入元素(二分查找)
4.4 统计函数
4.4.1 np.unique() #去除重复元素
4.4.2 np.bincount() #对整数数组的元素计数
4.4.3 np.histogram() #直方图统计
4.5 分段函数
4.5.1 np.where() #if
4.5.2 np.select() #多分支的if
4.5.3 np.piecewise() #分段函数
4.6 操作多维数组
4.6.1 np.concatenate() #连接多个数组
4.6.2 np.vstack() #沿第0轴连接数组
4.6.3 np.hstack() #沿第1轴连接数组
4.6.4 np.c[] #按列连接多个一维数组
4.6.5 np.split()、np.array_split() #将数组分为多段
4.6.6 np.transpose()、np.swapaxes() #重新设置轴的顺序
4.6.7 np.swapaxes() #交换两个轴的顺序
4.7 多项式函数
4.7.1 np.poly1d() #转化成poly1d对象
4.7.2 deriv() #计算微分
4.7.3 integ() #计算积分
4.7.4 np.roots() #求根
4.7.5 np.poly() #用根求多项式方程
4.7.6 np.polyfit() #拟合多项式函数
4.8 多项式函数类
4.8.1 np.polynomial.Polynomial() #创建Polynomial对象
4.8.2 p.deriv() #计算导函数
4.8.3 np.polynomial.Chebyshev()(拓展)
4.9 各种乘积运算
4.9.1 np.dot() #矩阵乘积
4.9.2 np.inner() #内积
4.9.3 np.outer() #外积
4.9.4 np.tensordot() #张量乘积
简介
NumPy提供了两种基本的对象:
1.ndarry:储存单一数据类型的多维数组
2.nfunc:对数组进行处理的特殊函数
查看numpy库的版本:
import numpy
print(numpy.__version__)
结果如下:
1.19.2
1.ndarray对象
1.1 创建数组
1.1.1 np.array()
用np.array()创建数组,括号中可以是列表、元组、多维列表:
import numpy as np
a = np.array([1,2,3])
b = np.array((1,2,3))
c = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(a)
print(b)
print(c)
结果如下:
[1 2 3]
[1 2 3]
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
1.2 数组形状与元素类型
1.2.1 ndarray.shape #获得形状
用ndarray.shape可获得数组的形状,返回元组(几行,几列):
import numpy as np
a = np.array([1,2,3])
b = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(a.shape)
print(b.shape)
结果如下:
(3,)
(3, 4)
1.2.2 ndarray.reshape() #改变形状
用ndarray.reshape(x,y)可以改变数组形状:
import numpy as np
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(a)
b = a.reshape(2,6)
print(b)
结果如下:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
(ps.b是通过a的转化得来,因此在这之后对a操作也会引起b的变化,示例如下:)
import numpy as np
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
b = a.reshape(2,6)
a[0][0] = 100
print(a)
print(b)
结果如下:
[[100 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[100 2 3 4 5 6]
[ 7 8 9 10 11 12]]
1.2.3 ndarray.dtype #获得元素类型
ndarray.dtype可以得到数组元素的类型:
import numpy as np
a = np.array([1,2,3])
print(a.dtype)
结果如下:
int32
即32位的长整型(默认值与操作系统和Python有关)
1.2.4 ndarray.astype() #转换元素类型
astype()方法可以对数组的元素类型进行转换:
import numpy as np
a = np.array([1,2,3])
b = a.astype(np.float)
c = a.astype(np.complex)
print(b.dtype)
print(b)
print(c.dtype)
print(c)
结果如下:
float64
[1. 2. 3.]
complex128
[1.+0.j 2.+0.j 3.+0.j]
1.2.5 np.set_printoptions(precision = ) #控制小数点位数
该函数可以控制输出的数组中显示小数点位数
(set_printoptions()里还有很多参数,在此仅说明precision的意义)
import numpy as np
np.set_printoptions(precision = 3) #四舍五入保留三位小数
a = np.array([0.12345,2.54687])
print(a)
结果如下:
[0.123 2.547]
1.3 自动生成数组
1.3.1 np.arange() #等差一维数组
np.arange(start, stop, step)可以创建等差数列的一维数组,其中开始值和终值遵循“左闭右开”的原则,类似于list中的range()
import numpy as np
a = np.arange(0,1,0.1)
print(a)
结果如下:
[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
1.3.2 np.linspace() #等差一维数组
np.linspace(start, stop, number, endpoint = )中可以指定开始值、终值和元素个数,可以通过endpoint参数指定是否包含终值,endpoint = True 则包含终值(默认为True)
import numpy as np
a = np.linspace(0,1,10,endpoint = False)
print(a)
结果如下:
[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
1.3.3 np.logspace() #指数数组
np.logspace()与np.linspace()相似,其start和stop为10的幂,例如(0,3,3)表示从开始到
,元素数量为4的等比数列:
import numpy as np
a = np.logspace(0,3,4)
print(a)
结果如下:
[ 1. 10. 100. 1000.]
1.3.4 np.zeros()、np.ones()、np.empty()、np.full() #特殊数组
np.zeros():创建制定形状的全零数组
np.ones():创建制定形状的全一数组
np.empty():只分配数组所使用的内存
np.full():将元素初始化为指定的值
import numpy as np
a = np.zeros((2,3),int)
b = np.ones((2,3),int)
c = np.empty((2,3),float)
d = np.full((2,3),666)
print(a)
print(b)
print(c)
print(d)
结果如下:
[[0 0 0]
[0 0 0]]
[[1 1 1]
[1 1 1]]
[[1. 1.1 1.2]
[9.7 9.8 9.9]]
[[666 666 666]
[666 666 666]]
1.3.5 np.zeros_like()、np.ones_like()、np.empty_like()、np.full_like() #形状相同的特殊数组
括号中输入数组,创建与输入数组相同形状的全零数组、全一数组等等
以np.zeros_like()为例:
import numpy as np
a = [[1,2,3,4],[5,6,7,8]]
print(a)
b = np.zeros_like(a)
print(b)
结果如下:
[[1, 2, 3, 4], [5, 6, 7, 8]]
[[0 0 0 0]
[0 0 0 0]]
1.4 存取元素
1.4.1 下标、切片
与列表(list)中操作相同,不再赘述
1.4.2 ndarray[[ ]] #批量提取数组元素
两个[[ ]]中填入需要的元素下标,该操作可以提取ndarry指定下标的元素并组成一个新的数组:
import numpy as np
a = np.arange(10,20,1)
print(a)
b = a[[2,4,6,8]]
print(b)
结果如下:
[10 11 12 13 14 15 16 17 18 19]
[12 14 16 18]
这种方法中,可以理解为:b是将a中元素提取后重新创建的一个数组,因此a和b不共用内存,所以对a操作不会影响b,a和b是相互独立的,互不影响。
ndarray[[ ]]也可以快速修改指定下标位置处元素的值:
import numpy as np
a = np.arange(0,10,1)
print(a)
a[[2,4,6,8]] = 0,0,0,0
print(a)
结果如下:
[0 1 2 3 4 5 6 7 8 9]
[0 1 0 3 0 5 0 7 0 9]
1.4.3 ndarray.take() #获取元素
沿着指定轴获取元素
import numpy as np
a = np.arange(3*4).reshape(3,4)
print(a)
result = a.take(indices = 0,axis = 1)
print(result)
结果如下:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[0 4 8]
即:沿着axis = 1(纵轴)取第0列元素
1.4.3 np.compress() #通过布尔数组获取元素
沿着指定轴通过布尔数组获取元素
np.compress(condition, ndarray, axis = )
import numpy as np
a = np.array([0,1,-2,0,3])
print(a)
b = np.compress([1,0,1],a,axis = 0)
print(b)
c = np.compress([1,0,1,0,1],a,axis = 0)
print(c)
结果如下:
[ 0 1 -2 0 3]
[ 0 -2]
[ 0 -2 3]
即在数组a中,沿着axis = 0的轴(横轴),取布尔数组中真值对应下标的元素
1.5 多维数组
1.5.1 二维数组的创建
二维数组的创建实际上是一个加法表,由纵向量和横向量的元素相加而得,例如:
import numpy as np
a = np.arange(0,60,10).reshape(-1,1)
b = np.arange(0,6)
print(a)
print(b)
print(a+b)
结果如下:
[[ 0]
[10]
[20]
[30]
[40]
[50]]
[0 1 2 3 4 5]
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
[50 51 52 53 54 55]]
1.5.2 二维数组的切片
import numpy as np
a = np.arange(0,60,10).reshape(-1,1) + np.arange(0,6)
print(a)
print('\n')
print(a[0,3:5]) #表示第0行的第3到5个元素
print('\n')
print(a[4:,4:]) #第4行之后及第4列之后元素组成的数组
print('\n')
print(a[:,2]) #每一行的第二个元素组成的列表
print('\n')
print(a[2::2,::2])
结果如下:
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
[50 51 52 53 54 55]]
[3 4]
[[44 45]
[54 55]]
[ 2 12 22 32 42 52]
[[20 22 24]
[40 42 44]]
需要注意的是,b = a[0,3:5]这样的切片中,b是a的视图,他们共享数据,因此,改变a会对b造成影响
1.6 结构数组
1.6.1 定义结构数组 np.dtype()
创建一个dtype对象person,其参数是字典,键:'names','formats',
其中names定义结构中每个字段的名称;formats定义每个字段的类型:
'S30':长度为30个字节的字符串类型,(必须指明其长度)
'i':32位的整数类型,相当于'np.int32'
'f':32位的单精度浮点型,相当于'np.float32'
然后调用array()创建数组,通过dtype参数来制定创建的数组的元素类型为person
import numpy as np
person = np.dtype({
'names':['name','age','height'], #'names'是固定名称,不可更改,但name、age等可更改
'formats':['S30','i','f']}, #'formats'是固定名称,不可更改
align = True)
a = np.array([('Jia',20,177),('Zhang',19,159)],dtype = person)
print(a)
print(a.dtype)
结果如下:
[(b'Jia', 20, 177.) (b'Zhang', 19, 159.)]
{'names':['name','age','height'], 'formats':['S30','<i4','<f4'],
'offsets':[0,32,36], 'itemsize':40, 'aligned':True}
其中'<i4','<f4'的'<'表示低位字节在前,即小端模式(little endian);'>'表示高位字节在前,即大端模式(big endian);不显示则表示忽略字节顺序。
1.6.2 结构数组的存取
结构数组的存取和一般数组相同,通过下标就能获取:
import numpy as np
person = np.dtype({
'names':['name','age','height'],
'formats':['S30','i','f']},
align = True)
a = np.array([('Jia',20,177),('Zhang',19,159)],dtype = person)
print(a[0])
结果如下:
(b'Jia', 20, 177.)
需要注意的是,输出的结果长得像元组,但并不是元组,而是结构:
print(a[0].dtype)
结果如下:
{'names':['name','age','height'], 'formats':['S30','<i4','<f4'],
'offsets':[0,32,36], 'itemsize':40, 'aligned':True}
因此可以用字段名作为下标获取相应元素,也可以通过这种方法修改元素:
print(a[0]['name'])
结果如下:
b'Jia'
2.ufunc对象
2.1 四则运算
表达式 | 对应的ufunc函数 |
y = x1 + x2 | add(x1, x2 [ ,y]) |
y = x1 – x2 | subtract(x1, x2 [ ,y]) |
y = x1 * x2 | multiply(x1, x2 [ ,y]) |
y = x1 / x2 | divide(x1, x2 [ ,y]),如果两个数组的元素为整数,则用整数除法 |
y = x1 / x2 | true_divide(x1, x2 [ ,y]),总是返回精确的商 |
y = x1 // x2 | floor_divide(x1, x2 [ ,y]),总是对返回值取整 |
y = -x | negative(x [ ,y]) |
y = x1 ** x2 | power(x1, x2 [ ,y]) |
y = x1 % x2 | remainder(x1, x2 [ ,y]),mod(x1, x2 [ ,y]) |
用符号也可以直接运算:
import numpy as np
a = np.array([1,2,3])
b = np.array([3,2,1])
print(a+b)
print(a-b)
print(a*b)
print(a/b)
print(a//b)
print(-a)
print(a**b)
print(a%b)
结果如下:
[4 4 4]
[-2 0 2]
[3 4 3]
[0.33333333 1. 3. ]
[0 1 3]
[-1 -2 -3]
[1 4 3]
[1 0 0]
2.2 比较运算和布尔运算
2.2.1 比较运算(<,=,>)
比较两个数组的对应元素,如果满足要求则不二数组对应位置为True,否则为False
表达式 | 对应的ufunc函数 |
x1 == x2 | equal(x1, x2 [ ,y]) |
x1 != x2 | not_equal(x1, x2 [ ,y]) |
x1 < x2 | less(x1, x2 [ ,y]) |
x1 <= x2 | less_equal(x1, x2 [ ,y]) |
x1 > x2 | greater(x1, x2 [ ,y]) |
x1 >= x2 | greater_equal(x1, x2 [ ,y]) |
用符号也可以直接运算:
import numpy as np
a = np.array([1,2,3])
b = np.array([3,2,1])
print(a == b)
print(a != b)
print(a < b)
print(a <= b)
print(a > b)
print(a >= b)
结果如下:
[False True False]
[ True False True]
[ True False False]
[ True True False]
[False False True]
[False True True]
2.2.2 布尔运算(np.logical_and、or、not)
Python中布尔运算使用and、or、not关键字,无法被重载,因此数组的布尔运算只能通过相应的ufunc函数进行,他们都以“logical_”开头:logical_and()、logical_or()、logical_not()
import numpy as np
a = np.array([1,2,3])
b = np.array([3,2,1])
print(np.logical_and(a > b,a == b))
结果如下:
[False False False]
2.2.3 布尔运算(np.all()、np.any())
NumPy中也定义了np.any()和np.all()
np.any():只要有一个元素为True就返回True
np.all():只有当全部元素都为True才返回True
import numpy as np
a = np.array([0,1,2,3])
print(np.all(a))
print(np.any(a))
结果如下:
False
True
2.3 自定义ufunc函数
2.3.1 np.frompyfunc() #分段函数
通常情况下,自定义(def)出的函数只能计算单个值
例如:定义一个分段函数,小于-10时输出-1,在-10到10之间输出0,大于10输出1。
def f(a,b,x):
if x <= a:
return -1
if a < x <b:
return 0
if x >= b:
return 1
c = 6
result = f(-10,10,c)
print(result)
结果如下:
0
但如果此时c不再是一个数字,而是一串数字,例如列表、数组,这种函数就不能直接计算,只能多次调用,单独计算。通过np.frompyfunc()可以将计算单个值的函数转化为能对数组的每个元素进行计算的ufunc函数。
np.frompyfunc()的调用格式为:np.frompyfunc(func, nin, nout)。其中func:计算单个值的函数;nin:func中输入参数的个数;nout:func中返回值的个数。(注意:np.frompyfunc()只起到转换函数的作用,需要计算时要重新调用)
例如:定义一个分段函数,小于-10时输出-1,在-10到10之间输出0,大于10输出1
import numpy as np
def f(a,b,x):
if x <= a:
return -1
if a < x <b:
return 0
if x >= b:
return 1
function = np.frompyfunc(f,3,1) #只起到转换函数的作用
c = np.arange(-15,15,3)
result = function(-10,10,c) #计算时重新调用function()函数
print(c) #自变量
print(result) #分段函数输出的结果
结果如下:
[-15 -12 -9 -6 -3 0 3 6 9 12]
[-1 -1 0 0 0 0 0 0 0 1]
2.4 广播(broadcasting)
使用ufunc函数对两个数组计算时,会对两个数组的对应元素进行计算,因此要求两个数组形状相同。如果不同,会进行广播(broadcasting)处理
2.4.1 广播处理规则
①以维数最多的数组为准,其他数组向它看齐,shape属性中不足的部分通过在前面加1补齐;
②输出数组的shape属性是输入数组shape属性的各个轴上的最大值;
③如果输入数组的某个长度为1,或与输出数组的对应轴长度相同,则这个数组可以用来计算,否则出错;
④当输入数组的某个轴长度为1时,沿着该轴运算时,都用该轴上的第一组值。
具体实例:
先创建一个二维数组a,形状为(6, 1)
import numpy as np
a = np.arange(0,60,10).reshape(-1,1)
print(a)
print(a.shape)
结果如下:
[[ 0]
[10]
[20]
[30]
[40]
[50]]
(6, 1)
再创建一维数组b,其形状为(5, ):
import numpy as np
a = np.arange(0,60,10).reshape(-1,1)
b = np.arange(0,5)
print(b)
结果如下:
[0 1 2 3 4]
计算a与b的和,得到一个加法表,相当于计算两个数组中所有元素对的和,得到一个形状为(6, 5)的数组:
import numpy as np
a = np.arange(0,60,10).reshape(-1,1)
b = np.arange(0,5)
c = a+b
print(c)
结果如下:
[[ 0 1 2 3 4]
[10 11 12 13 14]
[20 21 22 23 24]
[30 31 32 33 34]
[40 41 42 43 44]
[50 51 52 53 54]]
由于a和b的维数不同,根据①,需要让b的shape属性向a对齐,于是在b的shape属性前补加1,变为(1, 5),即从 [0,1,2,3,4,5] 变成 [[0,1,2,3,4,5]],则a和b的shape变为(6, 1)和(1, 5),根据②,输出的数组长度为各个轴长度的最大值,则输出的c的shape属性为(6, 5)
由于b的第0轴(横着的,行)的长度为1,a的第0轴的长度为6,要把b的第0轴扩展成长度为6才能相加,即:
[[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]]
对a同理,则可以保证形状相同,才能相加。
2.4.2 np.broadcast_arrays() #查看广播之后的数组
np.broadcast_arrays()可以查看广播之后的数组,返回广播后的多个数组
import numpy as np
a = np.arange(2*3).reshape(2,3)
print(a)
print(a.shape)
b = np.array([1,2,3])
print(b)
print(b.shape)
result = np.broadcast_arrays(a,b)
print(result)
结果如下:
[[0 1 2]
[3 4 5]]
(2, 3)
[1 2 3]
(3,)
[array([[0, 1, 2],
[3, 4, 5]]),
array([[1, 2, 3],
[1, 2, 3]])]
2.4.3 ndarray.repeat() #复制元素
ndarray.repeat(复制的次数,axis = )
其中,axis = 0表示第0轴(列),即沿着axis = 0的轴,复制数组中各个元素的值
axis = 1表示第1轴(行),同理。
例1:对二维数组,沿第0轴复制
import numpy as np
a = np.array([[1,2,3,4,5]])
print(a)
c = a.repeat(3,axis = 0)
print(c)
结果如下:
[[1 2 3 4 5]]
[[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]]
例2:对一维数组,沿第0轴复制
import numpy as np
a = np.array([1,2,3,4,5])
print(a)
c = a.repeat(3,axis = 0)
print(c)
结果如下:
[1 2 3 4 5]
[1 1 1 2 2 2 3 3 3 4 4 4 5 5 5]
例3:对二维数组,沿第1轴复制
import numpy as np
a = np.array([[1,2,3,4,5]])
print(a)
c = a.repeat(3,axis = 1)
print(c)
结果如下:
[[1 2 3 4 5]]
[[1 1 1 2 2 2 3 3 3 4 4 4 5 5 5]]
2.4.4 下标对象None
表示在None对应的位置创建一个长度为1的新轴,例如:a[None, :]和a.reshape(1, -1)等效
import numpy as np
a = np.array([1,2,3,4,5])
print(a)
print(a[None,:])
print(a.reshape(1,-1))
print(a[:,None])
结果如下:
[1 2 3 4 5]
[[1 2 3 4 5]]
[[1 2 3 4 5]]
[[1]
[2]
[3]
[4]
[5]]
2.5 ufunc的方法
ufunc方法本身还有一些函数,这些方法只对2个输入、1个输出的ufunc函数有效,其他的ufunc对象调用这些方法时会抛出ValueError异常
2.5.1 np.<op>.reduce() #对数组内元素四则运算
np.<op>.reduce(array, axis = , dtype = )
<op>是指运算符,例如add、subtract、multiple、divide等等,该方法沿着axis指定的轴对数组进行操作,相当于沿着axis轴,将<op>添加到数组的各个元素之间,输出计算结果,例如:
import numpy as np
a = np.array([1,2,3,4])
b = np.add.reduce(a,axis=0) #1+2+3+4
print(b)
c = np.subtract.reduce(a,axis=0) #1-2-3-4
print(c)
d = np.multiply.reduce(a,axis=0) #1*2*3*4
print(d)
结果如下:
10
-8
24
2.5.2 np.<op>.accumulate() #对数组内元素四则运算
accumulate与reduce类似,只是返回与输入形状相同的数组,保存所有的中间计算过程:
import numpy as np
a = np.array([1,2,3,4])
b = np.add.accumulate(a,axis=0)
print(b) #[1,1+2,1+2+3,1+2+3+4]
c = np.subtract.accumulate(a,axis=0)
print(c) #[1,1-2,1-2-3,1-2-3-4]
d = np.multiply.accumulate(a,axis=0)
print(d) #[1,1*2,1*2*3,1*2*3*4]
结果如下:
[ 1 3 6 10]
[ 1 -1 -4 -8]
[ 1 2 6 24]
2.5.3 np.<op>.reduceat() 计算多组reduce()的结果
reduceat()方法计算多组reduce()的结果,通过indices参数指定一系列的起始和终止位置,例如:
import numpy as np
a = np.array([1,2,3,4])
result = np.add.reduceat(a,indices = [0,1,0,2,0,3,0])
print(result)
结果如下:
[ 1 2 3 3 6 4 10]
对于indices的每一个值,都会计算出一个值,结果中除了最后一个参数外,计算过程如下:
if indices[i] < indices[i+1]: #如果该元素小于后面一个元素
result[i] = <op>.reduce(a[indices[i]:indices[i+1]])
else: #如果该元素不小于后面一个元素
result[i] = a[indices[i]]
对于最后一个元素,计算过程如下:
<op>.reduce(a[indices[-1]:])
2.5.4 np.<op>.outer() #计算表
np.<op>.outer(a,b),其结果是一个计算表(加法表,乘法表,减法表),例如:
import numpy as np
a = np.array([1,2,3,4,5])
b = np.array([2,3,4])
result = np.multiply.outer(a,b)
print(result)
结果如下:
[[ 2 3 4]
[ 4 6 8]
[ 6 9 12]
[ 8 12 16]
[10 15 20]]
相当于是乘法表(加法,减法同理):
2 3 4
----------
1| 2 3 4
2| 4 6 8
3| 6 9 12
4| 8 12 16
5| 10 15 20
3.多维数组的下标存取
3.1 下标对象
多维数组的下标是一个“ 长度 = 数组维度 ”的数组,
如果下标的长度 > 数组维数,则会出错;
如果下标长度 < 数组维数,则会在下标元组后面补“ : ”,使得长度和维数相同。
———————————————————————-
如果下标对象不是元组,NumPy会先把他转化成元组,但这个过程可能与用户想的有出入,例如:a是一个三维数组,分别用 二维列表 和 二维数组 作为下标,输出是不一样的:
import numpy as np
a = np.arange(3*4*5).reshape(3,4,5)
print(a) #三维数组
b = tuple([[0],[1]]) #二维元组
c = np.array([[0],[1]]) #二维数组
print(a[b])
print(a[c])
结果如下:
[[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
[[20 21 22 23 24]
[25 26 27 28 29]
[30 31 32 33 34]
[35 36 37 38 39]]
[[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]]]
[[5 6 7 8 9]]
[[[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]]
[[[20 21 22 23 24]
[25 26 27 28 29]
[30 31 32 33 34]
[35 36 37 38 39]]]]
3.2 整数数组作为下标
如果下标元组的所有元素都是切片和整数,那么用它作为下标的得到的是原始数组的一个视图,即它和原始数组共享数据空间
3.3 布尔数组作为下标
布尔数组作为下标对象时,相当于用nonzero()将布尔数组转化成一组整数数组,然后用整数数组进行下标运算
3.3.1 np.nonzero() #找出不为0的元素
np.nonzero()返回数组中元素不为零的值的下标组成的数组,例如:
import numpy as np
a = np.array([0,1,-2,0,3])
print(a)
b = np.nonzero(a)
print(b)
结果如下:
[ 0 1 -2 0 3]
(array([1, 2, 4], dtype=int64),)
4.NumPy的函数库
4.1 随机数(np.random模块)
笔记函数总览:
函数名 | 功能 | 函数名 | 功能 |
rand | 0到1之间的随机数 | randn | 标准正态分布的随机数 |
randint | 指定范围内的随机整数 | normal | 正态分布 |
uniform | 均匀分布 | poisson | 泊松分布 |
permutation | 随机排列 | shuffle | 随机打乱顺序 |
choice | 随机抽取样本 | seed | 设置随机数种子 |
4.1.1 np.random.rand()(产生随机0~1浮点数)
产生0到1之间的随机浮点数,所有参数用于指定所产生数组的形状
import numpy as np
a = np.random.rand()
print(a)
b = np.random.rand(2,3)
print(b)
结果如下:
0.26454873391353306
[[0.32604263 0.61228564 0.92722863]
[0.3631769 0.53571405 0.04554973]]
4.1.2 np.random.randn()(产生正态分布随机数)
产生服从标准正态分布的随机数,参数含义与rand()相同
import numpy as np
a = np.random.randn()
print(a)
b = np.random.randn(2,3)
print(b)
结果如下:
-0.07751610157473836
[[ 0.20687204 0.41934397 -0.80796835]
[ 0.44276644 0.84450041 -0.41650222]]
4.1.3 np.random.randint()(产生随机整数)
产生指定范围内的随机整数,范围左闭右开
np.random.randint(start, stop, shape)
参数分别指定:起始值,终值,产生数组的形状(若没有这一项则默认返回一个随机整数)
import numpy as np
b = np.random.randint(0,10)
print(b)
c = np.random.randint(0,10,(2,3))
print(c)
结果如下:
3
[[5 8 9]
[5 2 3]]
4.1.4 np.random.normal()(随正态分布)
正态分布,其参数有三个,分别是:期望值、标准差、形状。例如:
import numpy as np
a = np.random.normal(100,10)
print(a)
b = np.random.normal(100,10,(2,3))
print(b)
结果如下:
97.37335368991738
[[ 99.207 88.422 113.329]
[100.994 81.526 99.495]]
4.1.5 np.random.uniform()(均匀分布)
均匀分布,其参数有三个,分别是:起始值、终值、形状。例如:
import numpy as np
a = np.random.uniform(10,20)
print(a)
b = np.random.uniform(10,20,(2,3))
print(b)
结果如下:
17.06049626065125
[[16.817 16.852 14.206]
[13.688 15.58 18.359]]
4.1.6 np.random.possion()(泊松分布)
泊松分布,其参数有两个,分别是:系数(单位时间或单位面积内随机事件的平均发生率)、形状。例如:
import numpy as np
a = np.random.poisson(2)
print(a)
b = np.random.poisson(2,(2,3))
print(b)
结果如下:
2
[[2 1 0]
[2 1 4]]
4.1.7 np.random.permutation() #产生乱序数组、打乱数组
产生一个乱序数组
当参数为整数n时,他返回 [0, n) 这n个整数的随机排列;
当参数为一个序列时,他返回这个序列的随机排列。
import numpy as np
r1 = np.random.permutation(6) #生成乱序数组
print(r1)
a = np.array([11,12,13,14,15,16]) #打乱数组
r2 = np.random.permutation(a)
print(r2)
结果如下:
[3 0 1 2 5 4]
[12 11 16 13 15 14]
4.1.8 np.random.shuffle() #打乱数组
将指定数组打乱,与permutation的区别是:
permutation将原数组中的元素打乱后放入新的数组中(产生了新的数组),对原数组没有影响;
shuffle直接改变原数组,将原数组打乱(不能产生新数组),是对原数组的操作,不能将其赋给新的变量
import numpy as np
a = np.array([11,12,13,14,15,16])
r1 = np.random.permutation(a)
print(r1)
print(a)
np.random.shuffle(a)
print(a)
结果如下:
[11 16 14 15 12 13] # a打乱后赋值给r1
[11 12 13 14 15 16] # a没有改变
[16 12 13 14 15 11] # a被改变
4.1.9 np.random.choice() #随机抽取
从指定样本中随机抽取
np.random.choice(ndarray, size = , replace = , p = )
size:用于指定输出数组的形状
replace:replace = True(默认)时,进行放回抽取;否则进行不放回抽取
p:指定每个元素的抽取概率(以列表或数组形式),如果不指定则默认为等概率抽取
当参数只有ndarray时,则返回随机抽取的一个数
import numpy as np
a = np.arange(10)
r1 = np.random.choice(a)
print(r1)
r2 = np.random.choice(a,size = (2,3),replace = True,p = a/np.sum(a))
print(r2)
结果如下:
2
[[1 7 5]
[8 7 2]]
4.1.10 np.random.seed() #种子
保证每次运行时出现相同的随机数,可以通过seed()指定随机数的种子
调用格式为:np.random.seed(num)
import numpy as np
np.random.seed(2)
a = np.random.rand()
print(a)
结果如下:
0.43599490214200376(运行无数次都是这个结果)
4.2 求和、平均值、方差
函数总览:
函数名 | 功能 | 函数名 | 功能 |
sum | 求和 | mean | 求期望 |
average | 加权平均数 | std | 标准差 |
var | 方差 | product | 连乘积 |
4.2.1 np.sum() #求和
对指定元素进行求和,可以对所有元素求和,沿行(列)求和,对指定轴求和
import numpy as np
a = np.arange(2*3).reshape(2,3)
print(a)
r1 = np.sum(a) #对所有元素求和
r2 = np.sum(a,axis = 0) #沿着行方向,对a的每一列求和
r3 = np.sum(a,axis = 1,dtype = float) #沿着列方向,对a的每一行求和
print(r1)
print(r2)
print(r3)
结果如下:
[[0 1 2]
[3 4 5]]
15
[3 5 7]
[ 3. 12.]
4.2.2 np.mean() #求平均数
求数组的平均值,参数与sum()相同
import numpy as np
a = np.arange(2*3).reshape(2,3)
print(a)
r1 = np.mean(a)
r2 = np.mean(a,axis = 0)
print(r1)
print(r2)
结果如下:
[[0 1 2]
[3 4 5]]
2.5
[1.5 2.5 3.5]
4.2.3 np.average() #计算加权平均数
average()也可以进行平均计算,特殊点在于:他有一个weights参数,可以计算加权平均数
import numpy as np
score = np.array([88,90,93])
number = np.array([15,25,30])
result = np.average(score,weights = number)
print(result)
结果如下:
90.85714285714286
4.2.4 np.std() #计算标准差
计算数组的标准差
np.std(ndarray, axis = , dtype= , out = , ddof= )
ddof = 0(默认)时,计算偏样本标准差;ddof = 1时,计算无偏样本标准差
import numpy as np
a = np.array([1,2,3,4,5,6])
r1 = np.std(a,axis = 0, ddof = 0)
r2 = np.std(a,axis = 0, ddof = 1)
print(r1)
print(r2)
结果如下:
1.707825127659933
1.8708286933869707
4.2.5 np.var() #计算方差
计算数组的方差,参数与np.std()一样
import numpy as np
a = np.array([1,2,3,4,5,6])
r1 = np.var(a,axis = 0, ddof = 0)
r2 = np.var(a,axis = 0, ddof = 1)
print(r1)
print(r2)
结果如下:
2.9166666666666665
3.5
4.2.6 np.product() #计算所有元素乘积
计算数组中所有元素的乘积
参数与np.sum()类似
import numpy as np
a = np.array([1,2,3,4,5,6])
r1 = np.product(a)
print(r1)
结果如下:
720
4.3 大小与排序
函数总览
函数名 | 功能 | 函数名 | 功能 |
min | 最小值 | max | 最大值 |
minimum | 二元最小值 | maximum | 二元最大值 |
ptp | 极差 | argmin | 最小值的下标 |
argmax | 最大值的下标 | unravel_index | 一维下标转化成多维下标 |
sort | 数组排序 | argsort | 计算数组排序的下标 |
lexsort | 多列排序 | partition |
快速计算前k位 |
argpartition | 前k位的下标 | median | 中位数 |
percentile | 百分位数 | searchsorted | 二分查找 |
4.3.1 np.min(),np.max(),np.minimum(),np.maximum(),np.ptp()
np.min(),np.max(),np.minimum(),np.maximum()分别表示计算最小值、最大值、二元最小值、二元最大值、极差
前四个函数的用法与np.sum()类似,np.ptp()有axis和out参数,用法与之前类似,这里例举最简单的情况:
import numpy as np
a = np.array([-1,6,4,-7,3,4])
b = np.arange(2*3).reshape(2*3)
print(a)
r1 = np.min(a)
r2 = np.max(a)
r3 = np.ptp(a)
print(r1)
print(r2)
print(r3)
print(b)
r4 = np.minimum(a,b) #对比a和b对应位置的元素,选出两个中最小的一个,放入新数组的对应位置
r5 = np.maximum(a,b)
r6 = np.ptp(b)
print(r4)
print(r5)
print(r6)
结果如下:
[-1 6 4 -7 3 4] #a
-7 #min
6 #max
13 #max-min
[0 1 2 3 4 5] #b
[-1 1 2 -7 3 4] #minimum
[0 6 4 3 4 5] #maximum
5 #maximum-minimum
4.3.2 np.argmax(),np.argmin() #求最值下标
可以求最大值和最小值的下标
如果不指定axis参数,则返回平坦化(转化成一维数组)之后的数组下标
如果指定axis参数,可以沿着指定轴计算最大值的下标
import numpy as np
a = np.random.randint(0,10,size = (2,3))
r1 = np.argmax(a)
print(a)
print(r1)
结果如下:
[[8 9 0]
[1 1 4]]
1
4.3.3 np.unravel_index() #下标转化
可以将一维数组下标转化成多维数组的下标
np.unracel_index(下标, 多维数组的形状)
import numpy as np
a = np.random.randint(0,10,size = (2,3))
r1 = np.argmax(a)
print(a) #输出数组a
print(r1) #最大值在数组平坦化后的下标
r2 = np.unravel_index(r1,a.shape)
print(r2) #最大值在原数组形状下的下标
结果如下:
[[6 0 1]
[0 2 7]]
5
(1, 2)
4.3.4 np.sort() #排序
np.sort()可以对数组进行排序,并将排序后的值赋给新的数组
默认axis = 1(对每行数组进行排序)
axis = 0表示对每列数组进行排序
axis = None表示,将数组平坦化后进行排序
import numpy as np
np.random.seed(1)
a = np.random.randint(0,10,size = (3,4))
print(a)
r1 = np.sort(a)
r2 = np.sort(a,axis = 1)
r3 = np.sort(a,axis = 0)
r4 = np.sort(a,axis = None)
print(r1)
print(r2)
print(r3)
print(r4)
结果如下:
[[5 8 9 5]
[0 0 1 7]
[6 9 2 4]] #a
[[5 5 8 9]
[0 0 1 7]
[2 4 6 9]] #r1
[[5 5 8 9]
[0 0 1 7]
[2 4 6 9]] #r2
[[0 0 1 4]
[5 8 2 5]
[6 9 9 7]] #r3
[0 0 1 2 4 5 5 6 7 8 9 9] #r4
4.3.5 np.argsort() #排序后的下标
np.argsort()返回数组的排序下标,参数axis默认为-1
import numpy as np
np.random.seed(69)
a = np.random.randint(0,10,size = (5,))
print(a)
r1 = np.argsort(a)
print(r1)
结果如下:
[6 9 7 4 1]
[4 3 0 2 1]
即:a中1是最小的,其下标是4,所以4在r1[0];
以此类推,4是a中第二小的,其下标为3,所以3在r1[1]
4.3.6 np.lexsort() #多列排序
np.lexsort()类似于Excel中的多列排序,其参数为一个形状为(k, N)的数组,即包含k个长度为N的序列,可以理解成N行k列的表格,该方法返回排序下标,数组中最后的行为排序的主键(以数组中最后一行为标准进行排列)
例如:
import numpy as np
np.random.seed(69)
name = ['A','B','C','D','E']
age = [31,35,40,29,25]
r1 = np.lexsort([name,age]) #参数是一个2行5列的数组
print(r1)
结果如下:
[4 3 0 1 2]
即,以最后一行(age)为标准进行排序,所以返回age的下标排序
4.3.6 np.lexsort() 应用:成绩姓名全局排序
背景:A、B等5人乘积分别是95,93,87,99,96,将姓名与成绩对应,并按成绩由大到小排列
import numpy as np
np.random.seed(69)
name = ['A','B','C','D','E']
score = [95,93,87,99,96]
idx = np.lexsort([name,score])
print(idx)
r1 = list(zip(name,score))
l = []
for i in idx:
l.append(r1[i])
print(l)
结果如下:
[2 1 0 4 3]
[('C', 87), ('B', 93), ('A', 95), ('E', 96), ('D', 99)]
4.3.7 np.partition(),np.argpartition() #数组分割
np.partition(),np.argpartition()可以对数组进行分割,快速找出排序后数组的前k个元素(调用速度比sort()快很多)
np.partition(ndarray, kth = )
调用后,使新数组前kth个元素是原数组中最小的kth个,且这kth个也不按大小排序,只是把他们挑出来放在新数组的前面而已,剩余的放在后面随便排,例如:
import numpy as np
np.random.seed(69)
a = np.random.randint(0,10,size = (10,))
print(a)
r1 = np.partition(a,kth = 7)
print(r1)
结果如下:
[6 9 7 4 1 6 9 8 1 6]
[6 1 1 4 6 7 6 8 9 9]
即:r1的前7个元素是a中最小的7个,且在r1中没有按大小排序,只是把它们挑出来放在前七个位置上而已,后面的8,9,9是随便排的
如果需要将前7个排序,再调用一下np.sort()就可以:
import numpy as np
np.random.seed(69)
a = np.random.randint(0,10,size = (10,))
print(a)
r1 = np.partition(a,kth = 7)
print(r1)
r2 = np.sort(r1[:7])
print(r2)
结果如下:
[6 9 7 4 1 6 9 8 1 6]
[6 1 1 4 6 7 6 8 9 9]
[1 1 4 6 6 6 7]
np.argpartition()同理,只是返回的是下标而已:
import numpy as np
np.random.seed(69)
a = np.random.randint(0,10,size = (10,))
print(a)
r1 = np.argpartition(a,kth = 7)
print(r1)
r2 = np.sort(a[r1[:7]])
print(r2)
结果如下:
[6 9 7 4 1 6 9 8 1 6]
[5 4 8 3 0 2 9 7 6 1]
[1 1 4 6 6 6 7]
4.3.8 np.median() #计算中位数
np.median()可以获得数组的中值,即:先把数组排序,再取中值。当长度是偶数时,取中间两个数的平均数
可以指定axis参数
import numpy as np
np.random.seed(69)
a = np.random.randint(0,5,size = (5,))
print(np.sort(a))
r1 = np.median(a)
print(r1)
b = np.random.randint(0,6,size = (6,))
print(np.sort(b))
r2 = np.median(b)
print(r2)
结果如下:
[1 2 3 3 4]
3.0
[0 0 0 1 1 1]
0.5
4.3.9 np.percentile() #计算百分数
np.percentile()用于计算百分数,即:将元素从小大到排列,计算处于p%位置上的值
调用格式及参数:np.percentile(ndarray, p),其中p可以是一个数,也可以是一个数组
import numpy as np
a = np.array([1,2,3,4,5,6,7,8,9,10])
print(a)
r1 = np.percentile(a,[0,25,50,75,100])
print(r1)
结果如下:
[ 1 2 3 4 5 6 7 8 9 10]
[ 1. 3.25 5.5 7.75 10. ]
4.3.10 np.searchsorted() #插入元素(二分查找)
searchsorted(a, value, side='left')
a:已经排好序的升序数组(如果a不是升序的,则该方法会先将a升序排列)
value:插入数组a的值,可以是单个元素、列表、数组
side:可以填入‘left‘或‘right‘。left则返回第一个符合条件的元素下标;right则返回最后一个符合条件的元素下标,如果没有符合的元素,则返回0或N(数组a的长度),即应该插入到a的最开始或最末尾
若a中有value中的元素(假设该元素为i):
当side = left(默认)时:直接返回a中第一个i的下标
当side = right时:返回a中最后一个i的下标并+1
import numpy as np
a = np.array([2,2,2,2,4,8,16,32])
print(a)
r1 = np.searchsorted(a,2,side = 'left')
print(r1)
r2 = np.searchsorted(a,2,side = 'right')
print(r2)
结果如下:
[ 2 2 2 2 4 8 16 32]
0
4
若a中没有value中的元素:
将value的各个元素插入到a的合适位置,使插入后的元素value满足:
当side = left(默认)时:a[i-1] < value <= a[i](局部升序)
当side = right时:a[i-1] <= value < a[i](局部升序)
import numpy as np
a = np.array([2,4,8,16,32])
print(a)
r1 = np.searchsorted(a,[1,3,5,7,9,11])
print(r1)
r2 = np.searchsorted(a,[1,3,5,7,9,11],side = 'right')
print(r2)
结果如下:
[ 2 4 8 16 32]
[0 1 2 2 3 3]
[0 1 2 2 3 3]
4.4 统计函数
函数总览:
函数名 | 功能 | 函数名 | 功能 |
unique | 去除重复元素 | bincount | 对整数数组的元素计数 |
histogram | 一维直方图统计 |
4.4.1 np.unique() #去除重复元素
np.unique()返回去除重复元素后的数组,并按从小到大的顺序排列
np.unique(ndarray, return_index, return_inverse)
return_index:为True时,返回:新数组在原数组中的下标组成的数组,默认为False
return_inverse:为True时,返回:原始数组在新数组中的下标组成的数组,默认为False
import numpy as np
np.random.seed(1)
a = np.random.randint(0,10,size = (10,))
print(a)
r1 = np.unique(a,return_index = True,return_inverse = True)
print(r1)
结果如下:
[5 8 9 5 0 0 1 7 6 9]
(array([0, 1, 5, 6, 7, 8, 9]), #新数组
array([4, 6, 0, 8, 7, 1, 2], dtype=int64),
array([2, 5, 6, 2, 0, 0, 1, 4, 3, 6], dtype=int64))
4.4.2 np.bincount() #对整数数组的元素计数
np.bincount()对整数数组中各个元素的出现次数进行统计,要求原数组必须是非负的
np.bincount(ndarray, weights = )
返回一个数组,数组中下标为i的元素表示:数字i出现的次数
import numpy as np
np.random.seed(1)
a = np.random.randint(0,10,size = (10,))
print(a)
r1 = np.bincount(a)
print(r1)
结果如下:
[5 8 9 5 0 0 1 7 6 9]
[2 1 0 0 0 2 1 1 1 2]
即:0出现2次,1出现1次,3出现0次……
参数weights可以指定一个数组w,表示每个数所对应的权值。
返回数组a中的每个整数所对应的w中的权值之和,例如:
import numpy as np
np.random.seed(1)
a = np.random.randint(0,4,size = (5,))
print(a)
w = np.array([0.1,0.2,0.3,0.4,0.5])
print(w)
r1 = np.bincount(a,weights = w)
print(r1)
结果如下:
[1 3 0 0 3]
[0.1 0.2 0.3 0.4 0.5]
[0.7 0.1 0. 0.7]
即:0所对应的权值为0.3+0.4=0.7;1所对应的权值为0.1;
2所对应的权值为0;3所对应的权值为0.2+0.5=0.7
所以返回[0.7, 0.1, 0, 0.7]
4.4.3 np.histogram() #直方图统计
np.histogram()对一维数组进行直方图统计
np.histogram(ndarray, bis = , range = , weights = , density = )
bis:统计区间的个数,bis是一个数,则将统计范围等分成bis份;若bis是一个数组,则可以实现区间的不等分,例如[0, 0.1, 0.3, 0.4, 0.9, 1]
range:该参数是一个长度为2的元组,表示统计范围的最小值和最大值。默认为None,即(a.min(), a.max())
weights:与np.biscount()中的weights类似,表示权值,若指定weights参数,则对区间中数值所对应的权值进行求和
density:为False时,返回ndarray的数据在每个区间中的个数;True时,返回每个区间的概率密度
该方法返回两个一维数组:hist和bin_edges。hist是每个区间的统计结果,bin_edges是hist所对应的区间,的长度是len(hist)+1,每两个相邻数值构成一个统计区间
例如:
import numpy as np
np.random.seed(1)
a = np.random.rand(100)
r1 = np.histogram(a,bins = 5,range = (0,1))
print(r1)
结果如下:
(array([24, 16, 21, 20, 19], dtype=int64),
array([0. , 0.2, 0.4, 0.6, 0.8, 1. ]))
即:生成100个0~1之间的随机数,然后将区间(0, 1)等分成5份,结果显示有24(第一个数组的结果)个元素在0~0.2(第二个数组的结果)之间,16个元素在0.2~0.4之间……
4.5 分段函数
函数总览
函数名 | 功能 | 函数名 | 功能 |
where |
矢量化判断表达式 |
piecewise | 分段函数 |
select | 多分支判断选择 |
4.5.1 np.where() #if
x = np.where(condition, y, z)
其中condition, y, z都是数组,其返回值是一个形状与condition相同的数组
当condition中的某个元素为True时,x中对应下标的值从数组y获取,否则从z获取
import numpy as np
np.random.seed(1)
x = np.random.randint(0,10,size = (5,))
print(x)
y = np.where(x<5,'yes','no')
print(y)
结果如下:
[5 8 9 5 0]
['no' 'no' 'no' 'no' 'yes']
4.5.2 np.select() #多分支的if
如果分段函数分段的数量很多,就需要用np.where()一层一层嵌套,不利于编写与阅读用np.select()就可以解决这个问题
select(condlist, choicelist, default = 0)
condlist:长度为N的布尔数组列表(必须是列表形式),用于判断分段的条件(例如x是否<5)
choicelist:长度为N的储存候选值的数组列表(必须是列表形式),用于具体计算
default:当所有条件都不满足时,用default填上
关于布尔数组,例如:
import numpy as np
np.random.seed(1)
a = np.random.randint(0,10,size = 5)
print(a)
x = [a<5] #布尔数组
print(x)
结果如下:
[5 8 9 5 0]
[array([False, False, False, False, True])]
对于np.select的具体用法,
例如:分段函数:x<5时,y=x**2;5<=x<=10时,y=-x;x>10时,y=0
import numpy as np
np.random.seed(5)
x = np.random.randint(0,15,size = 10)
print(x)
#指明自变量分段的条件
condition = [x<5,
np.logical_and(x>=5,x<=10), #用逻辑运算,Python不支持5<=x<=10
x>10]
#指明各段的函数
choice = [x**2,-x,0]
y = np.select(condition,choice)
print(y)
结果如下:
[ 3 14 13 6 6 0 9 8 4 7]
[ 9 0 0 -6 -6 0 -9 -8 16 -7]
4.5.3 np.piecewise() #分段函数
尽管用np.select,如果输入的数组很大,计算时会产生许多保存中间结果的数组,会发生大量内存分配和释放。为了解决这个问题,有np.piecewise()专门计算分段函数
np.piecewise(x, condlist, funclist)
condlist:长度为M的布尔数组列表
funclist:长度为M或M+1的函数列表,这些函数的输入和输出都是数组;如果长度为M,则正常计算;如果长度为M+1,则最后一个函数计算所有条件都为False时的值
例如:分段函数:x<5时,y=x**2;5<=x<=10时,y=-x;x>10时,y=0
import numpy as np
np.random.seed(5)
x = np.random.randint(0,15,size = 10)
print(x)
#指明自变量分段的条件
condition = [x<5,
np.logical_and(x>=5,x<=10), #用逻辑运算,Python不支持5<=x<=10
x>10]
#指明各段的函数,此处需要用lambda
funclist = [lambda x:x**2,
lambda x:-x,
0]
y = np.piecewise(x,condition,funclist)
print(y)
结果如下:
[ 3 14 13 6 6 0 9 8 4 7]
[ 9 0 0 -6 -6 0 -9 -8 16 -7]
4.6 操作多维数组
函数总览
函数名 | 功能 | 函数名 | 功能 |
concatenate | 连接多个数组 | vstack | 沿第0轴连接数组 |
hstack、c_[] | 沿第1轴连接数组 | column_stack | 按列连接多个一维数组 |
split、array_split | 将数组分为多段 | transpose | 重新设置轴的顺序 |
swapaxes | 交换两个轴的顺序 |
4.6.1 np.concatenate() #连接多个数组
用于连接多个数组,第一个参数为需要连接的数组,用()括起来,第二个参数是axis,用于指定沿axis轴进行连接,默认为0
import numpy as np
np.random.seed(5)
a = np.zeros((3,3))
b = np.ones((3,3))
r1 = np.concatenate((a,b))
print(r1)
r2 = np.concatenate((a,b),axis = 1)
print(r2)
结果如下:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[0. 0. 0. 1. 1. 1.]
[0. 0. 0. 1. 1. 1.]
[0. 0. 0. 1. 1. 1.]]
4.6.2 np.vstack() #沿第0轴连接数组
np.vstack()用于沿着第0轴连接数组,当被连接数组是长度为N的一维数组时,将其形状改为(1, N)
其参数为要连接的数组,用()括起来
import numpy as np
np.random.seed(5)
a = np.zeros((3,3))
b = np.ones((3,3))
r1 = np.vstack((a,b))
print(r1)
结果如下:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
4.6.3 np.hstack() #沿第1轴连接数组
与np.vstack()相似,沿着第1轴连接数组,当所有数组都是一维时,沿着第0周连接数组
import numpy as np
np.random.seed(5)
a = np.zeros((3,3))
b = np.ones((3,3))
r1 = np.hstack((a,b))
print(r1)
结果如下:
[[0. 0. 0. 1. 1. 1.]
[0. 0. 0. 1. 1. 1.]
[0. 0. 0. 1. 1. 1.]]
4.6.4 np.c[] #按列连接多个一维数组
和np.hstack()一样,按列连接数组
调用格式为:np.c_[a,b]
import numpy as np
np.random.seed(5)
a = np.zeros((3,3))
b = np.ones((3,3))
r1 = np.c_[a,b]
print(r1)
结果如下:
[[0. 0. 0. 1. 1. 1.]
[0. 0. 0. 1. 1. 1.]
[0. 0. 0. 1. 1. 1.]]
4.6.5 np.split()、np.array_split() #将数组分为多段
np.split()、np.array_split()用法基本相同,将一个数组沿着指定轴分成多个数组,可以直接或指定切分轴上的切分点下标
np.split(a, indices_or_sections, axis=0)
indices_or_sections:类型为int或一维数组,表示切的位置。如果值是一个整数n的话,就将数组平均分为n份(如果不能平均分则报错);如果是一个数组的话,就医数组中的数字为索引切开
axis:对于二维数组,axis = 0表示横向切(用刀横着切数组),axis = 表示纵向切
具体见下方实例:
1.当 indices_or_sections为整数时):
import numpy as np
np.random.seed(5)
a = np.arange(1,10).reshape(3,3)
print(a)
r1 = np.split(a,3) # indices_or_sections为整数
print(r1)
A,B,C = np.split(a,3) # indices_or_sections为整数
print(A)
print(B)
print(C)
结果如下:
[[1 2 3]
[4 5 6]
[7 8 9]]
[array([[1, 2, 3]]), array([[4, 5, 6]]), array([[7, 8, 9]])]
[[1 2 3]]
[[4 5 6]]
[[7 8 9]]
2.当 indices_or_sections为数组时(axis = 0):
import numpy as np
np.random.seed(5)
a = np.arange(5*6).reshape(5,6)
print(a)
A,B,C = np.split(a,[1,4])
print(A)
print(B)
print(C)
结果如下:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]]
#横向切(横着切),在纵向下标为1和4处分隔
[[0 1 2 3 4 5]]
[[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[24 25 26 27 28 29]]
3.当 indices_or_sections为数组时(axis = 0):
import numpy as np
np.random.seed(5)
a = np.arange(5*6).reshape(5,6)
print(a)
A,B,C = np.split(a,[1,4],axis = 1)
print(A)
print(B)
print(C)
结果如下:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]]
#纵向切(竖着切),在横向下标为1和4处分隔
[[ 0]
[ 6]
[12]
[18]
[24]]
[[ 1 2 3]
[ 7 8 9]
[13 14 15]
[19 20 21]
[25 26 27]]
[[ 4 5]
[10 11]
[16 17]
[22 23]
[28 29]]
4.6.6 np.transpose()、np.swapaxes() #重新设置轴的顺序
np.transpose()用于修改轴的顺序
例如:np.transpose(a,[1,2,0])表示:新数组的第0轴存放a的第1轴,新数组的第1轴存放a的第2轴,新数组的第2轴存放a的第0轴
import numpy as np
a = np.arange(1*2*3).reshape(1,2,3)
print(a.shape)
r1 = np.transpose(a,[1,2,0])
print(r1.shape)
结果如下:
(1, 2, 3)
(2, 1, 3)
4.6.7 np.swapaxes() #交换两个轴的顺序
np.swapaxes()用于交换两个轴的顺序
例如:np.swapaxes(a,0,1)表示:将a的第0轴和第1轴交换顺序
import numpy as np
a = np.arange(2*3*4).reshape(2,3,4)
print(a.shape)
r1 = np.swapaxes(a,0,1)
print(r1.shape)
结果如下:
(2, 3, 4)
(3, 2, 4)
4.7 多项式函数
4.7.1 np.poly1d() #转化成poly1d对象
np.poly1d()可以将列表、数组转化成poly1d对象,该对象可以像函数一样调用
import numpy as np
a = np.array([1,2,3])
r1 = np.poly1d(a)
print(r1)
结果如下:
2
1 x + 2 x + 3
即表示:
用法1:可以像函数一样被调用:
import numpy as np
a = np.array([1,2,3])
f = np.poly1d(a)
print(f)
r1 = f(2) #x=2带入
print(r1)
结果如下:
2
1 x + 2 x + 3
11 #表示x=2时上式的结果
用法2:多项式的四则运算
import numpy as np
a = np.array([1,2,3])
f = np.poly1d(a)
print(f)
print(f + [5,5])
print(f*2)
print(f*f)
print(f/[1,3])
结果如下:
2
1 x + 2 x - 3 # f
2
1 x + 7 x + 2 # f + [5,5]
2
2 x + 4 x - 6 # f*2
4 3 2
1 x + 4 x - 2 x - 12 x + 9 # f*f
(poly1d([ 1., -1.]), poly1d([0.])) #f/[1,3]
#返回两个poly1d类型的元素,第一个是商,第二个是余数
4.7.2 deriv() #计算微分
deriv()用于计算多项式函数的微分,调用格式为:poly1d对象.deriv()
import numpy as np
a = np.array([1,2,-3])
f = np.poly1d(a)
print(f)
r1 = f.deriv()
print(r1)
结果如下:
2
1 x + 2 x - 3
2 x + 2
4.7.3 integ() #计算积分
integ()用于计算多项式函数的积分,调用格式为:poly1d对象.integ()
import numpy as np
a = np.array([1,2,-3])
f = np.poly1d(a)
print(f)
r1 = f.integ()
print(r1)
结果如下:
2
1 x + 2 x - 3
3 2
0.3333 x + 1 x - 3 x
4.7.4 np.roots() #求根
np.roots()用于计算多项式函数的根,调用格式为:np.roots(poly1d对象)
import numpy as np
a = np.array([1,2,-3])
f = np.poly1d(a)
print(f)
r1 = np.roots(f)
print(r1)
结果如下:
2
1 x + 2 x - 3
[-3. 1.]
4.7.5 np.poly() #用根求多项式方程
np.poly()可以通过根求多项式系数
import numpy as np
a = np.array([1,2])
r1 = np.poly(a)
print(r1)
结果如下:
[ 1. -3. 2.]
4.7.6 np.polyfit() #拟合多项式函数
np.polyfit():根据数据拟合出相应的多项式函数,找出与这组数据的误差平方最小的多项式的系数
np.polyfit(x, y, 最高次的次数)
import numpy as np
a = np.array([1,2,3,4,5])
b = np.array([1,4,9,16,25])
r1 = np.polyfit(a,b,3)
print(r1)
结果如下:
[ 1.62920807e-17 1.00000000e+00 -4.54973822e-15 2.70557374e-15]
4.8 多项式函数类
np.polynomial中提供了更丰富的多项式函数类,其中多项式各项的系数按照幂从小到大的顺序排列(与4.7相反)
4.8.1 np.polynomial.Polynomial() #创建Polynomial对象
np.polynomial.Polynomial()可以创建Polynomial对象,并计算多项式函数
import numpy as np
a = np.array([1,2,3])
f = np.polynomial.Polynomial(a)
r1 = f(2) #计算1*(2^0) + 2*(2^1) + 3*(2^2)
print(r1)
结果如下:
17.0
4.8.2 p.deriv() #计算导函数
对于Ploynomial对象,p.deriv()可以计算导函数:
import numpy as np
a = np.array([1,2,3])
f = np.polynomial.Polynomial(a)
r1 = f.deriv()
print(r1)
结果如下:
poly([2. 6.])
即:,求导得
4.8.3 np.polynomial.Chebyshev()(拓展)
切比雪夫多项式是一个正交多项式序列,一个n次多项式可以表示为多个切比雪夫多项式的加权和
使用Chebyshev类表示由切比雪夫多项式组成的多项式
多项式可由Chebyshev.basis(i)获得
1.利用convert方法转换多项式类型
语句:Chebyshev.basis(i).convert(kind = )
例如:将转化成Polynomial类:
import numpy as np
a = np.polynomial.Chebyshev.basis(4)
print(a)
r1 = a.convert(kind = np.polynomial.Polynomial)
print(r1)
结果如下:
cheb([0. 0. 0. 0. 1.])
poly([ 1. 0. -8. 0. 8.])
即:
2.切比雪夫节点
切比雪夫多项式的根称为切比雪夫节点可以用于多项式插值。相应的差值多项式能最大程度降低龙格现象(等距插值多项式在两端有很大的振荡),并且提供多项式在连续函数的最佳一致逼近。
详细查看(p101)
4.9 各种乘积运算
函数总览
函数名 | 功能 | 函数名 | 功能 |
dot | 矩阵乘积 | inner | 内积 |
outer | 外积 | tensordot | 张量乘积 |
4.9.1 np.dot() #矩阵乘积
对于一维数组,其计算内积;对于二维数组,其计算矩阵乘积
通用公式:dot(a, b)[i, j, k, m] = sum(a[i, j, :] * b[k , :, m])
对于一维数组:直接计算内积,即向量点乘
import numpy as np
#一维数组
a = np.arange(3)
b = np.array([2,3,4])
print(a)
print(b)
r1 = np.dot(a,b)
print(r1)
结果如下:
[0 1 2]
[2 3 4]
11 # 0*2 + 1*3 + 2*4
对于二维数组:进行矩阵乘法(第一行乘第一列,m*n与n*k才能相乘)
import numpy as np
# 二维数组
a = np.arange(6).reshape(3,2)
b = np.array([[2,3,4],[5,6,7]])
print(a)
print(b)
r1 = np.dot(a,b)
print(r1)
结果如下:
[[0 1]
[2 3]
[4 5]]
[[2 3 4]
[5 6 7]]
[[ 5 6 7]
[19 24 29]
[33 42 51]]
4.9.2 np.inner() #内积
np.inner()用于计算内积
对于一维数组,inner()和dot()一样,
对于二维数组,具体计算过程见下例
计算内积时,需保证两个矩阵形状相同!!!
import numpy as np
# 二维数组
a = np.arange(6).reshape(2,3)
b = np.array([[2,3,4],[5,6,7]])
print(a)
print(b)
r1 = np.inner(a,b)
print(r1)
结果如下:
[[0 1 2] # a行
[3 4 5]] # b行
[[2 3 4] # c行
[5 6 7]] # d行
[[11 20] # [a*c a*d]
[38 74]] # [b*c b*d]
4.9.3 np.outer() #外积
np,outer()用于计算外积,且只对一维数组进行计算,如果传入的是多维数组,先将数组展平为一维数组再计算(具体计算过程见下例)
对于一维数组:
import numpy as np
# 一维数组
a = np.arange(3)
b = np.array([2,3,4])
print(a)
print(b)
r1 = np.outer(a,b)
print(r1)
结果如下:
[0 1 2]
[2 3 4]
[[0 0 0] # [0*2 0*3 0*4] 或 [a11*b11 a11*b12 a11*b13]
[2 3 4] # [1*2 1*3 1*4]
[4 6 8]] # [2*2 2*3 2*4]
对于二维数组:
import numpy as np
# 二维数组
a = np.arange(6).reshape(2,3)
b = np.array([[2,3,4],[5,6,7]])
print(a)
print(b)
r1 = np.outer(a,b)
print(r1)
结果如下:
[[0 1 2]
[3 4 5]]
[[2 3 4]
[5 6 7]]
[[ 0 0 0 0 0 0] # [0*2 0*3 0*4 0*5 0*6 0*7]
[ 2 3 4 5 6 7] # [1*2 1*3 1*4 1*5 1*6 1*7]
[ 4 6 8 10 12 14] # ……
[ 6 9 12 15 18 21]
[ 8 12 16 20 24 28]
[10 15 20 25 30 35]]
4.9.4 np.tensordot() #张量乘积
np.tensordot()将两个多维数组a和b指定轴上的对应元素相乘并求和
np.tensordot(a,b,axes = [[轴1],[轴2]])
axes有两个参数,第一个表示a中的轴,第二个表示b中的轴,该方法会将指定轴的对应元素相乘再相加
(即:第一?和第一?相乘并相加,放在a11,第一?和第二?相乘再相加,放在a12,……其中轴1和轴2分别控制两个问号,0表示列,1表示行。例如:axes = [[0],[1]]表示第一列和第一行相乘并相加,放在a11,以此类推……)
如果axes是整数,则表示把a中的后axes个轴和b中的前axes个轴进行相乘再相加的运算,其他轴保持不变
import numpy as np
# 二维数组
a = np.arange(9).reshape(3,3)
b = np.array([[2,3,4],[5,6,7],[8,9,10]])
print(a)
print(b)
r1 = np.tensordot(a,b,axes = [[0],[0]]) #表示a的列和b的列相乘,放在a11……
print(r1)
结果如下:
[[0 1 2]
[3 4 5]
[6 7 8]]
[[ 2 3 4]
[ 5 6 7]
[ 8 9 10]]
[[ 63 72 81]
[ 78 90 102]
[ 93 108 123]]
作者:AAA村口卖鸭子小贾