numpy基础和应用

数组对象基础

数组也是对象,其类型是numpy.ndarray

组成数组的元素必须是同一类型,这点与列表是不一样的。

NumPy数组对象的常用属性:

dtype:返回数组元素的类型

shape:返回由整数组成的元祖,元组中的每一个整数依次对应数组的每个轴的元素个数

size:数组中元素的个数

ndim:数组的轴的个数,即维度

nbytes:保存数组的字节数

创建数组

np.array()

object参数所引用的对象是array_like(类数组,可以是列表,元祖等可迭代序列,也可以是数组,矩阵)

numpy中创建特殊数组的函数

①同一种元素的数组

创建元素值为1的数组:ones(以元祖的形式指定形状)     ones_like(指定数组)

同理 zeros,zeros_like,empty,empty_like

②np.eye()   np.identity()   np.diag()都能创建对角线元素比较特殊而其他部分元素为0的数组

#根据k来调整对角线的位置
data=np.eye(4,dtype=int,k=1)
"""
运行结果:
[[0 1 0 0]
 [0 0 1 0]
 [0 0 0 1]
 [0 0 0 0]]
"""
#而np.identity()创建的是不能调整对角线的单位矩阵
data=np.identity(4)
"""
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
"""
#比较灵活的是,np.diag()
data=np.diag([1,2,3,4],k=-1)
"""
[[0 0 0 0 0]
 [1 0 0 0 0]
 [0 2 0 0 0]
 [0 0 3 0 0]
 [0 0 0 4 0]]
"""
#第二个作用
data=np.arange(16).reshape((4,4))
"""
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
"""
data1=np.diag(data,k=-1)
"""
[ 4  9 14]
"""

③创建元素是等差和等比的数组

#通过arange()函数 创建一维数组 开始值,结束值,步长 前包括后不包括
data=np.arange(1,10,3)
"""[1 4 7]"""

#linspace()   开始值,结束值,数组的长度(数列总共有的数值的个数)
# 有一个参数endpoint=True 来调控是否包含末尾的值  默认是true即包括
data=np.linspace(1,10,4)
"""[ 1.  4.  7. 10.]"""

#返回的是等比数列元素组成的数组
data=np.logspace(2,3,num=4)
"""[ 100.          215.443469    464.15888336 1000.        ]"""

④创建自定义类型的数组

使用方法是np.dtype()方法,注意是方法,与属性的区别

data.dtype    data是数组对象,返回的是数组元素的类型

#my_type是自定义的dtype对象,参数是一个字典,字典有两个键”names“ 和”formats“
# formats规定了相应字段的类型  S30表示长度为30字节的字符串类型
my_type=np.dtype({"names":['name','age'],"formats":['S30',np.int_]})
#另一种定义方式
#my_type=np.dtype([('name','S30'),('age',np.int_)])
students=np.array([('shatinhui',21),('zhangsan',16)],dtype=my_type)
#  [(b'shatinhui', 21) (b'zhangsan', 16)]

数组的索引

①下标是整数

c=np.logspace(1,3,12).reshape(3,4)
"""
[[  10.           15.19911083   23.101297     35.11191734]
 [  53.36699231   81.11308308  123.28467394  187.38174229]
 [ 284.80358684  432.87612811  657.93322466 1000.        ]]
"""
c[1][2]
c[(1,2)]
c[1,2]
#这三种写法是一样的
"""123.28467394420659"""

②下标是列表

对于一维数组,下标如果是一个列表,则可以列表中元素值为索引依次从数组中取值,并且生成一个新的数组

b=np.linspace(0,100,5)
# [  0.  25.  50.  75. 100.]
three=b[0],b[2],b[3]
# (0.0, 50.0, 75.0)
three2=b[[0,2,3]]
# [ 0. 50. 75.]  返回的是一个数组对象,并且是一个新数组,跟原来的数组没有关系。
c=np.logspace(1,3,12).reshape(3,4)
"""
[[  10.           15.19911083   23.101297     35.11191734]
 [  53.36699231   81.11308308  123.28467394  187.38174229]
 [ 284.80358684  432.87612811  657.93322466 1000.        ]]
"""
c[[0,2]]
"""
[[  10.           15.19911083   23.101297     35.11191734]
 [ 284.80358684  432.87612811  657.93322466 1000.        ]]
"""
c[[0,2],[1,2]]
# [ 15.19911083 657.93322466]   相当于取c[0][1] 和c[0][2]

③下标是数组

b=np.linspace(0,100,5)
b[1]=100
#[  0. 100.  50.  75. 100.]
v=np.array([0,1,3])
r=b[v]
print(r)
print(b[[0,1,3]])
# 结果都是[  0. 100.  75.]
#列表可以看做"类数组"对象,那么下标是数组和下标是列表的操作应该非常相似

下标是数组的情况,不局限于下标是列表的情况,看下面程序下标是布尔型数组的情况。

b=np.linspace(0,100,5)
b[1]=100
#[  0. 100.  50.  75. 100.]
t=b==50
print(t)
# [False False  True False False]  数组元素变成布尔型
print(b[t])  #[50.]
print(b[b>60])  #[100.  75. 100.]

数组的切片

切片用来设定某一范围,根据这个范围从原数组中得到部分元素。

通过切片得到的数组和原数组共享一个内存空间,通常称为公用同一视图,当其中一个进行修改时,另一个也随之修改, 这跟上面通过下标得到的新数组是不一样的,他们不共享同一存储空间。

关于切片理解方式:先根据0轴的要求进行切片,然后将得到的结果根据1轴进行切片。

练习题

数组的操作

数组变形

a=np.arange(10)
#通过reshape方法对数组a变形,得到一个新数组,他们不公用同一视图
b=np.reshape(a,(2,5))
"""
[[0 1 2 3 4]
 [5 6 7 8 9]]
"""
c=np.reshape(b,(-1,1))  #使用一个不存在的数,让numpy自动推断0轴上应该有的元素个数
"""
[[0]
 [1]
 [2]
 [3]
 [4]
 [5]
 [6]
 [7]
 [8]
 [9]]
"""

除使用reshape()方法外,也可以使用数组的shape属性进行变形,但这种方式不是生成一个新的数组

将数组扁平化——变成一维数组 数组对象.flatten(),不在同一视图

相同作用的reval(),区别:在同一视图

使用下标操作完成变形

data=np.arange(5)
c=data[:,np.newaxis]
"""
[[0]
 [1]
 [2]
 [3]
 [4]]
"""
#将数组的某个轴设置为np.newaxis即None

data2=np.expand_dims(data,axis=1)
"""
[[0]
 [1]
 [2]
 [3]
 [4]]
"""
#np.expand_dims()作用是根据轴来调整数组形状

数组的组合

①水平组合

np.hstack(tup)  tup是元祖,包含即将被组合在一起的几个数组

这几个数组要求其0轴方向的形状一致,而1轴的形状可以不同

a=np.arange(9).reshape((3,3))
b=np.arange(12).reshape((3,4))
np.hstack((a,b))
"""
[[ 0  1  2  0  1  2  3]
 [ 3  4  5  4  5  6  7]
 [ 6  7  8  8  9 10 11]]
"""

实现水平组合的另外两种方法:

np.stack()    它要求每一个数组有相同的形状

np.concatenate((a,b),axis=1) #水平组合就是沿着1轴组合

②垂直组合

np.vstack()要求被组合的数组在1轴方向上的形状相同

同样可以使用np.concatenate()方法,传入轴的参数 axis=0

③其他组合

#深度组合
a=np.arange(9).reshape((3,3))
b=a*3
np.dstack((a,b))
"""
[[[ 0  0]
  [ 1  3]
  [ 2  6]]

 [[ 3  9]
  [ 4 12]
  [ 5 15]]

 [[ 6 18]
  [ 7 21]
  [ 8 24]]]
"""
#深度组合,把a,b想象成两个平面,一上一下,然后沿着竖直方向组合上下对应的元素,形成三个竖直的面,它们就是新生成的数组
#列组合
one=np.arange(5)
two=np.arange(5,10)
np.column_stack((one,two))
"""
[[0 5]
 [1 6]
 [2 7]
 [3 8]
 [4 9]]
"""
#行组合
np.row_stack((one,two))
"""
[[0 1 2 3 4]
 [5 6 7 8 9]]
"""

数组的分割

a=np.arange(24).reshape((4,6))
np.split(a,2,axis=1)
"""
[array([[ 0,  1,  2],
       [ 6,  7,  8],
       [12, 13, 14],
       [18, 19, 20]]), array([[ 3,  4,  5],
       [ 9, 10, 11],
       [15, 16, 17],
       [21, 22, 23]])]
"""
np.hsplit(a,2)
"""
[array([[ 0,  1,  2],
       [ 6,  7,  8],
       [12, 13, 14],
       [18, 19, 20]]), array([[ 3,  4,  5],
       [ 9, 10, 11],
       [15, 16, 17],
       [21, 22, 23]])]
"""
np.vsplit(a,2)
"""
[array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11]]), array([[12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])]
"""

改编元素

改编元素是指修改数组已有元素(通过索引),增加,修改元素(通过np.append(),np.insert(),np.delete()三个方法,实质都是创建了一个新的数组,跟原来数组没有关系)

a=np.array([[1,2,3],[4,5,6]])
b=np.array([[7,8,9]])
r=np.append(a,b,axis=0)
"""
[[1 2 3]
 [4 5 6]
 [7 8 9]]
"""
a1=a.flatten()
r=np.insert(a1,1,88)  
# [ 1 88  2  3  4  5  6]
np.delete(a,1,axis=0)
# [[1 2 3]]

 运算

①算数运算

一个数组和一个标量进行加、减、乘、除运算,结果是数组的每一个元素都与该标量进行相应的运算,并返回一个新数组

原则上,只有形状一样的数组才能进行运算。

某种情况,就是numpy将某个数组通过广播的方式进行临时转换,使得两个数组的形状符合原则上的要求

a=np.arange(10).reshape(2,5)
m=np.arange(5)
a+m #两个数组在1轴上长度一样
"""
[[ 0  2  4  6  8]
 [ 5  7  9 11 13]]
"""
n=np.arange(1,3).reshape(-1,1)   #两个数组在0轴上长度一致
print(a+n)
"""
[[ 1  2  3  4  5]
 [ 7  8  9 10 11]]
"""

②比较运算和逻辑运算

比较运算要求两个数组的形状一样,一一对应地进行比较,然后以布尔型数组形式返回比较结果

a=np.array([3,6,9])
b=np.array([4,5,8])
print(np.any(a<b) and np.any(a>b)) #True
print(np.all(a<b))  #False
print((a<b).all()) #False

通用函数

①内置函数  常用的一元函数和二元函数,用的时候查表

②自定义通用函数

def bmi(height,weight):
    bmi_index=weight/height**2
    if bmi_index>=18 and bmi_index<=25:
        return 0
    elif bmi_index<18:
        return -1
    else:
        return 1

#np.random随机抽样
#其random_sample()方法返回随机的浮点数,在[0.0,1.0)之间
#所以要产生[a,b)随机的浮点数,(b-a)*np.random.random_sample()+a
h=(2.1-1.4)*np.random.random_sample((10,))+1.4
h=np.round(h,2) #四舍五入,保留2位小数
w=(100-40)*np.random.random_sample((10,))+40
w=np.round(w,2)

#第一种方式
#使用np.frompyfunc()  使之成为能够针对数组元素进行操作的函数
bmi_ufunc=np.frompyfunc(bmi,2,1)   #bmi函数接收的参数为2个,返回的对象1个
print(bmi_ufunc(h,w))
#[1 0 1 1 1 1 0 0 -1 0]

#第二种方式
#np.vectorize() 将函数对象矢量化
bmi_ufunc2=np.vectorize(bmi,otypes=[np.float_]) #通过otypes设置返回数组的元素类型
print(bmi_ufunc2(h,w))
#[ 1.  0.  0.  0.  0.  1.  1. -1.  0.  1.]

简单统计应用

1.生成正态分布数据 +统计函数的使用

np.random.normal([loc, scale, size])

loc即μ  分布的平均值,scale即 \sigma  分布的标准差,size为输出的数据个数

np.random.randn(size) 生成标准正态分布

g=np.random.randn(10)
g1=np.random.randn(10)
g=(g-g.min())/10   #这两个语句什么意思,为什么要除以10
g1=(g1-g1.min())/10
math=np.round((100-40)*g+40,1)
english=np.round((100-40)*g1+40,1)
marks=np.vstack((math,english))   #垂直组合
"""
[[50.9 45.3 44.3 54.3 41.6 40.  46.5 47.6 43.4 49.9]
 [45.9 51.4 46.9 50.5 60.6 40.  45.9 50.8 46.9 49.3]]
"""
print(np.mean(marks,axis=1)) #在1轴上计算平均值,那么就是英语和数学的平均值
print(np.mean(marks,axis=0)) #在0轴上计算平均值,就是每个学生两门成绩的平均值

#np.where()函数的使用     有点像三元操作符
print(np.where(math>np.mean(math),'',''))
#['差' '差' '差' '好' '好' '差' '好' '差' '好' '差']
print(np.where(math>np.mean(math)))
# (array([1, 2, 3, 5, 8], dtype=int64),)   返回的是符合条件的元素索引组成的数组

#np.select()的使用
"""
比平均分高5分的为好
比平均分高但少于5分的为良
其他为中
"""
print(np.select([math>np.mean(math)+5,np.logical_and(math>=np.mean(math),math<=np.mean(math)+5)],
                ['',''],default=''))
#['好' '好' '好' '中' '良' '中' '中' '中' '中' '中']

#np.piecewise()
"""
第一个参数 对象
第二个参数 条件列表
第三个参数 执行的操作列表  第二个参数和第三个参数要相对应
返回一个array对象
"""
print(np.piecewise(math,[math>np.mean(math)+5,np.logical_and(math>=np.mean(math),math<=np.mean(math)+5)],
                   [100,60]))
#[100.   0.  60.  60.   0. 100.   0.  60.   0.   0.]

矩阵

矩阵是ndarray的子类,因此它继承了数组的属性和方法,然后也有自己特有的属性和方法(矩阵乘法,矩阵幂)

创建矩阵

a=np.mat([1,2,3])
# [[1 2 3]]
a=np.mat('1 2 3;4 5 6;7 8 9')  #以字符串作为参数来创建矩阵
"""
[[1 2 3]
 [4 5 6]
 [7 8 9]]
"""
a1=np.mat(np.arange(10))    #也可以以数组作为参数创建矩阵

#也可以以矩阵为参数创建新的矩阵
m1=np.mat(np.eye(2))
m2=2*m1
r=np.bmat('m1 m2;m2 m1')
"""
[[1. 0. 2. 0.]
 [0. 1. 0. 2.]
 [2. 0. 1. 0.]
 [0. 2. 0. 1.]]
"""

矩阵的乘法

如果对二维数组的操作,实现类似乘法的操作,函数是np.dot()

a=np.arange(1,10).reshape(3,3)
b=np.array([[1,0,1],[0,1,1],[1,1,0]])
print(a*b)  #两个矩阵的对应元素相乘
"""
[[1 0 3]
 [0 5 6]
 [7 8 0]]
"""
print(np.mat(a)*np.mat(b))  #矩阵乘法
print(np.dot(a,b))   #点乘,实现矩阵乘法,还有其他用途,在下面
"""
[[ 4  5  3]
 [10 11  9]
 [16 17 15]]
"""

基本操作

转置 A.T

逆矩阵 A.I

矩阵幂

numpy有一个专门的模块来针对线性代数,模块名称为linalg(Linear algebra),可以完成更多矩阵的计算,包括求特征值,解线性方程组,计算行列式等

矢量运算

标量:只有大小没有方向

矢量:既有大小,右有方向

矢量与矢量的加减运算

f1=np.array([10*math.cos(math.pi/6),10*math.sin(math.pi/6)])
f2=np.array([0,12])
f=f1+f2

print(np.sqrt(np.sum(f**2)))
#在没有别的参数的情况下,np.linalg.norm输入一个vector,
# 就是计算vector的长度:vector的每个component的平方相加后开根号。
print(np.linalg.norm(f))

标量积

也叫数量积,点积,内积

两个矢量相乘的结果是标量

前面用过的np.dot():

对于一维数组,就是进行标量积运算(比如求做功,功=力*位移,两个都是矢量)

对于二维数组,就是矩阵乘法

一维数组除了使用np.dot()进行标量积运算外,我们还可以使用np.inner(),两者在一维无区别,对于多维是有区别的,如下

矢量积

又叫叉积或者外积,其结果也是矢量,方向是与两个矢量所构成的平面垂直

使用np.cross()求解矢量积(比如,求三个点围成的三角形面积)

观察np.outer() ,参数对象是一维数组表示的矢量,如果不是一维数组,自动将其展平为一维数组

v=np.array([1,2,3])
b=np.array([9,8,7])
print(np.outer(v,b))
"""
[[ 9  8  7]
 [18 16 14]
 [27 24 21]]
"""

张量积

这个之前没有听过

np.tensordot()的使用

a=np.arange(6).reshape(2,3)
b=np.arange(9).reshape(3,3)
print(np.dot(a,b))
print(np.tensordot(a,b,axes=([1],[0])))
#根据标量积的规则,a的1轴上的各元素与b的0轴上的各元素对应相乘并求和
"""
[[15 18 21]
 [42 54 66]]
"""

下面这段,不是很懂

对于numpy.random.randint用法

c=np.random.randint(2,size=(2,3,5))
d=np.random.randint(2,size=(3,2,4))
print(np.tensordot(c,d,axes=((0,1),(1,0))))
"""
[[1 1 2 2]
 [1 1 2 1]
 [1 0 1 1]
 [2 1 3 2]
 [0 2 1 2]]
"""

综合应用示列

多项式

补充一点:lambda函数

lambda匿名函数的格式:冒号前是参数,可以有多个,用逗号隔开,冒号右边为表达式,返回值是函数的地址,也就是函数对象

#使用numpy.ploy1d(),以一维数组为参数,创建一个多项式
a=np.array([1,-2,1])
p=np.poly1d(a)
"""
   2
1 x - 2 x + 1
"""

#创建 f(x)=(x-1)的平方+3(x-1)+1
g=np.poly1d([1,3,1])
f=lambda x:g(x-1)
print(f(1))  #结果为1
numpy.ploy1d(c_or_r,r=False,variable=None)
参数r=False(默认) 表示多项式的系数 ,如果 r=True表示多项式的根
variable表示多项式变量的符号,它接收的是一个字符串
a=np.array([1,-2,1])
p=np.poly1d(a,r=True,variable='a')
"""
   3
1 a - 3 a + 2
"""

多项式计算

#多项式加减乘除
#可以把类数组对象直接与多项式计算

a=np.array([1,-2,1])
p=np.poly1d(a)
print(p+[-1,1])
"""
 2
1 x - 3 x + 2
"""
print(p/[-1,1])  #除法注意余数
"""
(poly1d([-1.,  1.]), poly1d([0.]))
"""

#微分
print(p.deriv())   #2 x - 2
#积分(integral)
print(p.integ())
"""
        3     2
0.3333 x - 1 x + 1 x
"""
#求多项式的根
print(np.roots(p))
# [1. 1.]

拟合多项式

对某些数据使用多项式函数进行拟合的方法:numpy.polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False),前三个参数是必须的,第三个参数表示多项式次数

提供多项式操作方法的模块  numpy.polynomial

求解线性方程组

"""
求解方程组
3a+b=9
a+2b=8
"""
a=np.array([[3,1],[1,2]])
b=np.array([9,8])
x=np.linalg.solve(a,b)
#[2. 3.]
posted @ 2021-05-17 09:16  我的愿望是如你所愿  阅读(173)  评论(0)    收藏  举报