Numpy(Numerical Python),Python的一种开源的数值计算扩展
我觉得比较简单好理解的显示结果就不会在文中再体现出来,我更愿意在这篇博客中写下我遇到过的坑,以及自己对于一些方法的个人理解,如果读者有需要还是更建议全部自己敲一遍。我学的时候是全部都自己敲了一遍,并在这过程中才能发现许多问题。代码看着简单,其实并不简单,谁敲谁知道。
直接使用numpy中的array方法就可以创建数组了,如果输入的是一个列表则创建数组,输入多个列表这样数据就有两个维度就会变成矩阵了。除了我们直接手动指明数组内容的创建方式,numpy中还提供一些快速操作,如创建全0数组,全1数组等便捷操作,下面进行具体展开。
import numpy as np
# 一维array
a = np.array([2,23,4], dtype=np.int32) # np.int默认为int32,dtype可以指定array的数据类型
print(a)
print(a.dtype) #显示array的数据类型
# 多维array
a = np.array([[2,3,4],
[3,4,5]])
print(a) # 生成2行3列的矩阵
a = np.zeros((3,4))
print(a) # 生成3行4列的全零矩阵
# 创建全一数据,同时指定数据类型
a = np.ones((3,4),dtype=np.int)
print(a)
如何表示空的概念?其实这边创建出来数组中的数据都是无限小的、无限接近于0但不是0,这方便我们数学上的一些操作
# 创建全空数组,其实每个值都是接近于零的数
a = np.empty((3,4))
print(a)
[[6.23042070e-307 3.56043053e-307 1.37961641e-306 2.22518251e-306]
[1.33511969e-306 6.23037317e-307 6.23053954e-307 1.37962185e-306]
[1.11261027e-306 6.89805151e-307 1.78020169e-306 1.42410974e-306]]
和Python中的range()类似,同样是要指定起始点和终止点,可以指定步长或者反向步长,同样是左开右闭。但是range就不能直接返回一个列表了
# 创建连续数组
a = np.arange(10,21,2) # 10-20的数据,步长为2
print(a)
# 使用reshape改变上述数据的形状
b = a.reshape((2,3))
print(b)
也可以称为线性等分向量(linear space),在一个指定区间内按照指定的步长,将区间均等分,生成的是一个线段类型的数组。生成的线性间隔数据中,是有把区间的两端加进去的
# 创建线段型数据
a = np.linspace(1,10,20) # 开始端1,结束端10,且分割成20个数据,生成线段
print(a)
# 同时也可以reshape
b = a.reshape((5,4))
print(b)
利用random.rand() 可以创建出指定尺寸的数组
a = np.random.rand(3,4)
b = np.random.rand(2)
print(a,"\n",b)
这些方法都是用上面方法创建出来的数组的内置方法
print('number of dim:', array.ndim)
print('shape:',array.shape)
print('size:',array.size)
对数组使用astype()可以转换数据类型。
print('type',array.dtype)
先假设现在有两个一维数组
import numpy as np
# 一维矩阵运算
a = np.array([10,20,30,40])
b = np.arange(4)
print(a,b)
会在两个数组的相同对应位置上进行相加减,然后返回各个位置被相加减后结果的同样尺寸数组
c = a - b
d = a + b
print(c,d)
[10 19 28 37]
[10 21 32 43]
将对应的元素相乘除,返回的是同样尺寸的数组
c = a * b
d = b / a
print(c)
print(d)
[ 0 20 60 120]
[0. 0.05 0.06666667 0.075 ]
两种方法在一维数组中效果中都一样,都是返回对应元素相乘后相加的结果,返回的是一个数值
c = a.dot(b)
d = np.dot(a,b)
print(c)
print(d)
200
200
和Python中指数的写法一样,直接对array进行指数运算**
就行了
# 在Numpy中,想要求出矩阵中各个元素的乘方需要依赖双星符号 **,以二次方举例,即:
c = b**2
print(c)
print(A[np.newaxis,:]) # [1 1 1]变为[[1 1 1]]
[[1 1 1]]
print(A[np.newaxis,:].shape) # (3,)变为(1, 3)
(1, 3)
print(A[:,np.newaxis])
[[1]
[1]
[1]]
数组除了可以与数组进行运算之外,还可以与标量进行加减乘除,其结果就是数组中的每一个元素都与标量进行运算后汇总后的结果
data1 = np.array([[1, 2, 3], [4, 5, 6]])
data2 = 10
print(data1 + data2) # 数组相加
[[11, 12, 13]
[14, 15, 16]]
pritn(data1 * data2) #数组相乘
[[10, 20, 30],
[40, 50, 60]]
x = np.array([12, 9, 13, 15]
y = np.array([11, 10, 4, 8]
np.maximum(x, y) # 两个数组元素级最大值的
[12, 10, 13, 15]
-返回两个数组对应位置上比较谁更大后的结果
np.greater(x, y) # 执行元素级的比较操作
[ True, False, True, True]
首先创建两个二维数组
a = np.array([[1,1],[0,1]])
b = np.arange(4).reshape((2,2))
print(a)
print(b)
[[1 1]
[0 1]]
[[0 1]
[2 3]]
多维数组有两种乘法,同样是用dot,但是这边dot用法和前面提到的一维数组中的点乘不一样,这边dot是用于矩阵乘法的。
# 多维度矩阵乘法
# 第一种乘法方式:
c = a.dot(b)
print(c)
# 第二种乘法:
c = np.dot(a,b)
print(c)
# 多维矩阵乘法不能直接使用'*'号
[[2 4]
[2 3]]
print(A)
[[14 13 12 11]
[10 9 8 7]
[ 6 5 4 3]]
# 矩阵转置
print(np.transpose(A))
[[14 10 6]
[13 9 5]
[12 8 4]
[11 7 3]]
print(A.T)
[[14 10 6]
[13 9 5]
[12 8 4]
[11 7 3]]
将原本数组中的数据范围修改成指定的数据范围,让所有数的取值都落入到自己指定的数据表示范围中去,不在指定范围内的数都会被强制修改为指定范围的最小值或者最大值。
Array_min表示矩阵A中的数,如果满足上述关系,则原数不变。否则,如果X,则将矩阵中X变为Array_min;如果X>Array_max
,则将矩阵中X变为Array_max
print(np.clip(A,5,9))
[[9 9 9 9]
[9 9 8 7]
[6 5 5 5]]
# 多维转一维
A = np.arange(3,15).reshape((3,4))
# print(A)
print(A.flatten())
# flat是一个迭代器,本身是一个object属性
[ 3 4 5 6 7 8 9 10 11 12 13 14]
其他操作和一维数组中类似,只有在乘法这块上不一样,只有多维数组才能实现矩阵乘法操作。
np.sin、np.cos、np.tan、np.arcsin、np.arccos、np.arctan这些都可以使用,在numpy库中都可以找到对应的函数方法。
# Numpy中具有很多的数学函数工具
c = np.sin(a)
print(c)
调用numpy中的内置方法min、max找到最值;
print(np.max(a))
print(np.min(a,axis=1))
除了可以找到数组中的最值,我们还可以找到数组中最值的索引。但返回的是在一维数组下的索引,即使是在多维数组中使用最值索引,返回的也是一维坐标,而不是多维坐标。
print(np.argmax(a))
print(np.argmin(a))
以下三种方法效果类似,同时都可以沿着指定的轴进行计算均值。mean和average类似但是在源码上略有不同。
print(np.mean(a))
print(np.average(a)
print(a.mean())
# 累加
print(np.cumsum(a))
print(a.sum())
# 中位数
print(np.median(a))
print(a.var())
print(a.std())
print(np.sqrt(a))
对数运算不指定底数,默认以 e e e 为底数。但我们也可以指定底数,但只能指定2或者10为底数。
print(np.log(a))
print(np.log2(a))
print(np.log10(a))
指数运算也可以直接用Python中的**进行指数运算,也可以用numpy中封装好的指数方法。
print(np.power(a,2))
将数组中的所有元素都以绝对值表示
print(np.abs(a))
对于多维数组的排序,只能在多维数组中的最小列表单位内部中排序。
# 仿照列表排序
A = np.arange(14,2,-1).reshape((3,4)) # -1表示反向递减一个步长
print(A)
[[14 13 12 11]
[10 9 8 7]
[ 6 5 4 3]]
print(np.sort(A))
[[11 12 13 14]
[ 7 8 9 10]
[ 3 4 5 6]]
Python中是可以对序列进行切片的,同样numpy中也提供了对数组的类切片操作,可以灵活根据指定的索引,取出我们所需的数组片段。
这个就是正常的用法,直接写数组下标就可以了
import numpy as np
A = np.arange(3,15)
print(A)
[ 3 4 5 6 7 8 9 10 11 12 13 14]
print(A[3])
B = A.reshape(3,4)
print(B)
[[ 3 4 5 6]
[ 7 8 9 10]
[11 12 13 14]]
print(B[2])
[11 12 13 14]
print(B[0][2])
print(B[0,2])
5
5
这里以矩阵举例,一维数组的切片做法和Python中的序列切片操作一样。
:
表示,从开头到结尾,Z[:,2]
表示矩阵中的第二列元素,和Python序列中切片的:
含义相同Z = np.arange(9).reshape(3,3)
print( Z[:,2] )
Z[1:,1:]
表示 行的取值范围是第一行到最后一行,列的取值范围是第一列到最后一列,最后行和列两个维度相重叠的部分,就是最后取到的数据Z[1:,1:]
[::2,::2]
表示行的步长为2,列的步长也为2相重叠下的部分Z[::2,::2]
Z[[0,1],[0,2]]
a = np.array([1,1,4,3])
b = np.arange(4)
print(a==b)
[False True False True]
print(b<2)
[ True True False False]
还可以通过写条件查询在使用索引访问数组时,这时就会返回一个列表表示条件查询的结果。例如:在一维数组中 取大于3 并且 可以被二整除 的元素
print(a[(a > 3)&(a % 2 == 0)])
可以对要合并的方向上尺寸相同的数组进行合并
A = np.array([1,1,1])
B = np.array([2,2,2])
print(np.vstack((A,B)))
# vertical stack 上下合并,对括号的两个整体操作。
[[1 1 1]
[2 2 2]]
# horizontal stack左右合并
D = np.hstack((A,B))
print(D)
[1 1 1 2 2 2]
numpy中独有的特性:广播Broadcasting
numpy数组间的基础运算是一对一,也就是a.shape==b.shape,但是当两者不一样的时候,就会自动触发广播机制。
不同尺寸的数组也可以直接做运算,在运算之前numpy会将两个数组扩展至相同的尺寸,然后再将相同位置的元素相加
from numpy import array
a = array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = array([0,1,2])
print(a+b)
[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
trailing dimensions compatible
,可以理解为矩阵进行乘法前的条件,否则会报错。一开始我以为挺简单的学这个Numpy库,结果我发现细节还是很多的,后面发现很灵活,没我想的那么简单。这篇我博客以为一晚上就能写完,结果花了我两天的时间在这上面。或者下次可以试试其他学习方法,这次一边学一边写博客,效率好像有点低,也可能我不太习惯。学习下一个库函数Scipy时,我看看要不要先手敲一边代码,再来考虑做笔记。