本次篇幅内容较大,我们会将numpy剩下的大部分的常见操作全部列举出来。
首先照例我们先生成一个简单的矩阵
# 选取0到10(不包括10)的数,结果乘2
a=np.arange(10)*2
a
输出:
array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
我们可以像python里的list一样,直接提取array里面的元素
a[5]
输出:
10
当然类似切片的操作也是完全没问题的
a[2:5]
输出:
array([4, 6, 8])
我们也可以对array里面的元素进行赋值操作
比如这样子
# 将前三个数赋值为100
a[0:3]=100
a
输出:
array([100, 100, 100, 6, 8, 10, 12, 14, 16, 18])
利用copy函数可以对我们已有的array进行复制操作
a_slice=a[0:5].copy()
a_slice
输出:
array([100, 100, 100, 6, 8])
接下来来介绍一下多维矩阵
def f(x,y):
return 4*x+y
b=np.fromfunction(f,(3,2),dtype=int)
b
定义函数 f()
np.fromfunction()意思是,通过定义的f函数,来生成矩阵。
生成的矩阵基础模型为
[[00],[01],
[10],[11],
[20],[21]]
通过x*4以及y得到如下结果
array([[0, 1],
[4, 5],
[8, 9]])
在这里我们得到的是一个二维矩阵
那么现在再来一次读取矩阵元素的操作
b[0]
输出:
array([0, 1])
我们可以看到b这个array的第一个元素也是一个array
那么如果我们要读取该矩阵第一个元素的第二个元素怎么办呢?
b[0][1]
可以输出得到:
1
ok,那我们继续练习操作,来生成一个5*5的,元素皆为0的array
c=np.zeros([5,5])
c
array([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
将该矩阵的列数赋值为length
# length 即为这个矩阵的列数
length=c.shape[1]
length
输出:
5
利用一个简单的for循环可以做到:
for i in range(length):
c[i]=i
print(c[i])
输出:
[0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1.]
[2. 2. 2. 2. 2.]
[3. 3. 3. 3. 3.]
[4. 4. 4. 4. 4.]
掌握了以上操作后,我们来做一个非常简单的小例子
假如我们需要一个array来处理25个工人在一周(五天)的工作时数
# 建立array,从周一到周五
# np.random.randn(5,5)生成的是一个5*5的矩阵,矩阵的值范围约从-1到1,是波动的
# np.random.randn (5,5) +8 的意思为,一天工作八小时,但是存在工作时间的合理波动,为8小时左右
# np.round 以及最后的 2 的意思是,结果取小数点2位
week_days=np.array(['Monday','Tuesday','Wednesday','Thursday','Friday'])
work_time=np.round(np.random.randn(5,5)+8,2)
work_time
输出为:
array([[ 7.61, 8.31, 9.14, 8.52, 7.49],
[ 7.46, 8.71, 9.95, 8.34, 7.2 ],
[ 8.26, 8.43, 8.47, 7.93, 6.51],
[ 7.78, 7.31, 6.83, 8.1 , 8.34],
[ 7.39, 10.81, 7.91, 7.22, 7.46]])
首先判断一下,工作日里,是否有Tuesday存在
week_days=='Tuesday'
输出:
array([False, True, False, False, False])
可以看到,当week_day这个array的元素为Tuesday时,输出为TRUE,其余情况输出为FALSE。
当输出为TRUE的时候
work_time[week_days=='Tuesday']
即可以输出work_time这个array第二行的元素
array([[7.46, 8.71, 9.95, 8.34, 7.2 ]])
在举例说明一下翻转矩阵
首先创建一个普通array
a=np.array([[1,2,3],[4,5,6]],dtype='float')
a
输出:
array([[1., 2., 3.],
[4., 5., 6.]])
# 翻转矩阵
a.T
输出:
array([[1., 4.],
[2., 5.],
[3., 6.]])
最基本的操作已经介绍完了,让我们继续进阶一下,介绍一下三维矩阵
# 此处np.array里面多了一个中括号
a=np.array([[[1,2,3,0],[3,4,5,2]]])
a
输出:
array([[[1, 2, 3, 0],
[3, 4, 5, 2]]])
此时查看它的shape
# 1,2,4 意思是,一堆,两行,四列,也就是三维矩阵
a.shape
输出:
(1, 2, 4)
我们也可以在这里用a.T来转化矩阵
# 此处用a.T 可以将其转化为 四堆,两行,一列
a.T
输出:
array([[[1],
[3]],
[[2],
[4]],
[[3],
[5]],
[[0],
[2]]])
如果此时,我们想要转换矩阵,但是不是直接用a.T来转换,我们想把矩阵从1,2,4转化成1,4,2的话,就要用到
a.transpose()
a.transpose()可以指定转变方式[0,2,1]
[0,2,1]的意思是,第一个维度不变,后两个维度交换,
这样形状就从(1,2,4)变成了(1,4,2)
a.transpose(0,2,1)
输出:
array([[[1, 3],
[2, 4],
[3, 5],
[0, 2]]])
我们当然还可以利用numpy来求一个矩阵的逆矩阵
# 求逆矩阵
m = np.array([[1,2,4],[3,4,5],[2,6,4]])
i = np.linalg.inv(m)
m
输出:
array([[1, 2, 4],
[3, 4, 5],
[2, 6, 4]])
i
输出得到:
array([[-0.63636364, 0.72727273, -0.27272727],
[-0.09090909, -0.18181818, 0.31818182],
[ 0.45454545, -0.09090909, -0.09090909]])
可以通过矩阵乘法,判断逆矩阵是否正确(当然是正确的···)
原矩阵和它的逆矩阵相乘,结果是斜边为1的矩阵
所以只要判断,两个矩阵相乘,是否可以得到斜边为1的矩阵,即可判断
np.allclose()意思是,判断两个矩阵是否相当,返回值为boolean类型
from numpy.linalg import inv
a=np.array([[1,2],[3,4]])
ainv=inv(a)
ainv
输出:
array([[-2. , 1. ],
[ 1.5, -0.5]])
输入:
np.allclose(np.dot(a,ainv),np.eye(2))
np.allclose(np.dot(ainv,a),np.eye(2))
输出:
True
矩阵当然也是可以求特征值的,虽然相对来说复杂了很多······用的地方不多
# 求特征值 eigenvalues
np.linalg.eig(m)
输出:
(array([11.+0.j, -1.+1.j, -1.-1.j]),
array([[ 3.92274066e-01+0.j , 7.55928946e-01+0.j ,
7.55928946e-01-0.j ],
[ 6.40026108e-01+0.j , -5.55111512e-17-0.37796447j,
-5.55111512e-17+0.37796447j],
[ 6.60672111e-01+0.j , -3.77964473e-01+0.37796447j,
-3.77964473e-01-0.37796447j]]))
继续继续~难度越来越大,越来越复杂!
我们继续来说说多维矩阵,生成一个三维矩阵
# 五堆,五行,两列
a3d=np.arange(50).reshape(5,5,2)
a3d
输出:
array([[[ 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]]])
利用transpose也可以来改变三维矩阵的形状
# 两堆,0行,一列
a3d.transpose(2,0,1)
输出:
array([[[ 0, 2, 4, 6, 8],
[10, 12, 14, 16, 18],
[20, 22, 24, 26, 28],
[30, 32, 34, 36, 38],
[40, 42, 44, 46, 48]],
[[ 1, 3, 5, 7, 9],
[11, 13, 15, 17, 19],
[21, 23, 25, 27, 29],
[31, 33, 35, 37, 39],
[41, 43, 45, 47, 49]]])
bincount函数相对来说更复杂了一点
# np.bincount 意思解释如下
# np.array出的一个数列,其中的数字包括0,1,2,3,7,其中的一些数字是可以被重复的,顺序无所谓
# 其中生成的 bincount 数列实际上是一种计数
# bincount 中,第一个1代表的是,np.array中,数字0的个数,是1个
# 第二个3代表的是,np.array中,数字1的个数,是3个
# 第三个1代表的是,np.array中,数字2的个数,是1个
# 以此类推···
np.bincount(np.array([0,1,1,3,2,1,7]))
输出:
array([1, 3, 1, 1, 0, 0, 0, 1], dtype=int64)
在举例试试
np.bincount(np.array([1,1,2,10,2,4,7]))
输出:
array([0, 2, 2, 0, 1, 0, 0, 1, 0, 0, 1], dtype=int64)
下一个介绍一下 where()函数,这一节就快结束啦,坚持一下!
# where function 的意思是
# np.where(C,A,B) 意思为,如满足 True,则输出A,如满足False,则输出B
# 所以np.where 输出的结果为 1,6,7,8
A=np.array([1,2,3,4])
B=np.array([5,6,7,8])
C=np.array([True,False,False,False])
np.where(C,A,B)
输出:
array([1, 6, 7, 8])
那么where函数的其他用法呢?先生成一个5*5的array,数字从-1到1随机分布
# where function 的其他用法
b=np.random.randn(5,5)
b
先输出:
Out[22]:
array([[ 0.22675817, -0.32968475, 0.97355875, 1.25403444, -0.71749803],
[-0.13194902, -0.63450846, 0.2376501 , 1.17265272, 0.09408381],
[-0.32555452, 1.60505397, 0.22411285, 0.96071262, 0.18240879],
[-0.70484547, 0.11088696, -0.44609117, -1.05065555, 2.04582062],
[-1.46425472, 1.3190111 , -1.16085506, 0.06465522, -0.48600749]])
然后利用where函数来判断
# 意思是,将b<0的值全部赋值为0,b>0的值,仍然为b
np.where(b<0,0,b)
输出:
array([[0.22675817, 0. , 0.97355875, 1.25403444, 0. ],
[0. , 0. , 0.2376501 , 1.17265272, 0.09408381],
[0. , 1.60505397, 0.22411285, 0.96071262, 0.18240879],
[0. , 0.11088696, 0. , 0. , 2.04582062],
[0. , 1.3190111 , 0. , 0.06465522, 0. ]])
最后是 in1d函数
# np.in1d (注意in1d这里第三个是数字1,不是字母l)
# np.in1d 的意思是,判断第一个array的元素,是否存在于第二个array中
# 返回值为 boolean型
e=np.array([1,2,3,3,4,4,5])
np.in1d([2,4,7],e)
输出:
array([ True, True, False])
终于大部分的numpy函数已经介绍完毕了
在之后的学习中,关于nump用到的函数应该就是上面列举的这些了~
是有点多啊···不过学习呢,没办法呀
下一节将会介绍python的下一个包,pandas的用法。
谢谢~