目录python
Numpy是在Python中涉及科学计算时确定会用到的,该库提供多维数组。虽然python含有array数组,可是对于大量数据进行高级数学和其余类型的操做时,使用Numpy数组比使用array更加有效率,更加简单。为何Numpy这么快,一个很重要的缘由就是矢量化,用近C的速度去作一些运算。(摘自官方文档)编程
a=np.array([1,2,3]) b=np.array([(1,2,3),(4,5,6)],dtype='float64') c=np.array([[1,2,3],[4,5,6]]) #注意下面第一种复数矩阵的建立结果中j所有为0 d=np.array([[1,2],[3,4]],dtype=complex) e=np.array([1+2j,2+3j])
结果:数组
[1 2 3] [[1. 2. 3.] [4. 5. 6.]] [[1 2 3] [4 5 6]] [[1.+0.j 2.+0.j] [3.+0.j 4.+0.j]] [1.+2.j 2.+3.j]
a=np.zeros((2,3))#全0 b=np.ones((2,3))#全1 c=np.empty((2,3))#全垃圾值 d=np.eye(2)#对角矩阵 e=np.full((2,2),6)#全为6 f=np.diag([1,2,3,4])#建立对角线为[1,2,3,4]的二维数组 运行结果: [[0. 0. 0.] [0. 0. 0.]] -------------------------- [[1. 1. 1.] [1. 1. 1.]] -------------------------- [[1. 1. 1.] [1. 1. 1.]] -------------------------- [[1. 0.] [0. 1.]] -------------------------- [[6 6] [6 6]] -------------------------- [[1 0 0 0] [0 2 0 0] [0 0 3 0] [0 0 0 4]]
a=np.random.random((2,2))#2x2的随机数组,取值范围在[0.0,1.0) #random与rand相同,randn()函数取值范围是标准正态分布 b=np.random.randint(4,15,size=(2,2))#取值范围[4,15)的整数数组 c=np.random.normal(0,0.1,size=(3,3))#均值为0,标准差为0.1的正态分布中随机抽取3x3的数组 结果: [[0.98271693 0.30466724] [0.13086 0.72070177]] -------------------------- [[10 11] [13 5]] -------------------------- [[-0.02855388 -0.0367391 0.07517827] [-0.03310269 0.08124156 -0.16556125] [-0.04000652 0.00365722 -0.03634599]]
a=np.arange(4,10)#[4,5,6,7,8,9] b=np.arange(4,10,3)#[4,7] c=np.linspace(0,10,6)#建立[0,10]之间含6个元素的array,各个元素的间隔相等,为(10-0)/(6-1) d=np.linspace(0,10,6,endpoint=False)#建立[0,10)之间含6个元素的array,各个元素的间隔相等,为(10-0)/6 f=np.linspace(0,5)#默认是50个数据 e=np.logspace(0,2,20)#和linspace相似,建立的是等比数列,生成10^0-10^2的20个元素的等比数列
描述了代码中没有任何显示的循环索引等,应用在元素级(即应用与对应元素间的运算)
Numpy中的+-*/都是指的矢量化运算,就是对应位置的元素作加减乘除操做,便再也不赘述。dom
用于描述操做的隐式逐元素行为的术语,描述了如何在算数运算期间处理不一样形状的数组,较小的数组在较大的数组上广播,以便他们具备兼容的形状,广播提供了一种矢量化数组操做的办法。
通常广播的规则:
从尾尺寸开始,向前发展,当两个数组的shape知足:1.从尾部开始具备的轴都相同 2.当对应轴不一样但其中的一个轴为1这两个条件只要知足其中的一个便可,不然会抛出异常:operands could not be broadcast together
最后的结果数组的大小是沿输入的每一个轴不是1的大小。
例如:ide
a shape:(2x4x3) b ( 3,) a与b是能够广播的 c (8x4x3) d ( 2x1) c和d是不能够广播的 由于倒数第二维既不相同,也不知足其中一个为1.(4和2)
基本索引:
对于数组有几个维度,就至关于有几个轴,最外层对应轴axis=0,axis日后递增,以此类推。
2维数据中 axis=0表示行,axis=1表示列
3维数据中 axis=0表示组,axis=1表示行,axis=2表示列
对于1维数组其索引和list相同,再也不赘述。函数
对于2维: a=np.array([[1,2,3],[4,5,6]]) a[0]表明[1,2,3],即第一行数据 a[0][1]与a[0,1]均表明2,可是两者有些区别: [0][1]先找到a[0]再找[1],a[0,1]则是直接定位 对于3维: a=np.array([[[1,2,3],[4,5,6]],[[4,5,6],[7,8,9]]]) 即: [[[1 2 3] [4 5 6]] [[4 5 6] [7 8 9]]] ----------------- a[0]= [[1 2 3] [4 5 6]] a[0,0]=[1 2 3] a[0,0,1]=1
花式索引:测试
a[[0,1,2]] 一个花式索引,获取最外层索引(axis=0)为0,1,2的数据 a[[1,3],[1,2]] 使用两个花式索引操做数组时,会将第一个花式索引做为最外面的索引(axis=0),第二个花式索引(axis=1),以此类推.例子是获取索引为[1,1]和[3,2]的元素。 a[[1,3],[[1],[2]]] 对于两个花式索引,当第二个花式索引为二维数组时,此时获取的是[[a[1,1],a[1,2]],[a[3,1],a[3,2]]至关于行与列的组合。对于当对数组的矩形部分的元素总体赋值时用获得。
布尔索引:spa
a=np.array([1,2,3]) print(a==1) #打印结果为:[ True False False],即为一个布尔类型的数组 将布尔类型的数组做为索引会返回布尔值为Ture对应位置的数据 a[a==1] #其值为[1] 当a为二维数组时,若是想对其中一行,或者一列利用布尔索引 a=np.array([[1,2,3],[4,5,6],[7,8,9]]) print(a[[True,False,True],1]) print(a[0,[True,False,True]]) 结果: [2 8] [1 3] 注意,布尔索引的长度要和二维数组列的元素个数和行的元素个数相同
切片的形式:i:j:k
i表明初始位置,j表明终止位置,k表明步长。
j是负数时被解释为n+j(n为切片维度中元素的数量)
未给出的部分 | k>0 | k<0
-------- | ----- |----
没有给出 i | 默认为0 | 默认n-1
没有给出 j |默认为n|默认-n-1
没有给出 k ,K默认为1。rest
对于二维数组 a[:,:-1]输出前n-1列全部行 a[:,-1]获取最后一列(结果是一维数组) a[:,n-1:]获取最后一列(结果是二维数组) a=np.array([[1,2,3,4],[5,6,7,8]]) print(a[1:4:3,1:4:2]) 结果:[[6 8]]
对于矩阵运算这部分,由于Numpy官方推荐使用数组,之后会把矩阵给删除,因此就使用数组作矩阵运算。
数组做矩阵乘积运算时,可使用@操做符,也可使用dot函数。
数组能够进行转置操做,能够采用T或者transpose函数转置。
一维数组的转置就是它自己。
T与transpose()的区别:
对于一维和二维是没有区别的,对于多维而言当使用T和 transpose()时,你会发现结果时同样的,3维的转置默认是将维度由axis(0,1,2)变为(2,1,0),因此默认两者相同。可是有时咱们须要对三维数组仅仅两个轴进行变换,因此此时只能用transpose,而不能使用T。code
#乘积: A@B A.dot(B) np.dot(A,B) 三者都是指A矩阵与B矩阵相乘 #转置: A.transpose(1,0,2) 将其axis=0的轴与axis=1的轴进行变换,可输出其shape进行观察。 #求逆矩阵 np.linalg.inv(x) #求x的逆矩阵
dot运算须要注意的地方:
1.一维数组和一维数组
一维数组和一维数组的dot运算获得的是一个标量,便是线性代数中的内积。
vec1 = np.array([1, 2, 3]) vec2 = np.array([1, 1, 1]) print(vec1.dot(vec2)) print(vec1*vec2) 结果: 6 [1 2 3]
2.二维数组和一维数组的点积
例如shape(2,3)二维数组dot一维数组shape(3,),会获得一维行向量, 至关于(2,3) * (3,) = (2,)
vec1 = np.array([1, 2, 3]) vec2 = np.array([[1, 1, 1],[1,1,2]]) vec2.dot(vec1) 结果: [6 9]
变换数组形态
1.reshape()改变数组的shape
2.使用ravel,flatten函数展平数组
两者均可以展平数组,flatten能够选择横向或者纵向展平。
a= np.array([[1, 1, 1],[1,1,2]]) a.ravel() #横向展平 结果: [1, 1, 1, 1, 1, 2] a.flatten() #横向展平 结果: [1, 1, 1, 1, 1, 2] a=np.array([[1,2,3],[4,5,6]]) a.flatten('F')#纵向展平 结果: [1 4 2 5 3 6]
遇到的其余方法:
np.arange(20)[:,np.newaxis] #指将一维数组变为列向量
3.将数组进行组合
使用hstack函数能够实现数组的横向组合,vstack能够实现数组的纵向组合,concatenate函数能够实现数组的横向和纵向组合,其中参数axis=1按照横向组合,axis=0按照纵向组合。
注意组合的两个数组须要知足的条件:除了链接轴以外的全部输入数组维度必须彻底匹配。(意思就是若是按照横向组合,须要纵向的长度是相同的,可是链接轴(横向不须要长度相同))
一维数组: e=np.array([1,2,3]) d=np.array([1,2,3]) print(np.vstack((d,e))) print(np.hstack((d,e))) 结果: [[1 2 3] [1 2 3]] [1 2 3 1 2 3] 二维数组: a=np.array([[1,2],[4,5]]) b=np.array([[7,8,9],[10,11,12]]) print(np.hstack((a,b))) 等同print(np.concatenate((a,b),axis=1)) a和b按横向组合时,要求其纵向长度相同都为2,可是其横向(链接轴)不须要长度相同,a横向为2,b横向为3 结果: [[ 1 2 7 8 9] [ 4 5 10 11 12]] a=np.array([[1,2,3],[4,5,6]]) b=np.array([[7,8,9],[10,11,12]]) print(np.vstack((a,b))) 也就等同print(np.concatenate((a,b),axis=0)) 结果: [[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]]
np.c_和np.r_
np.r_是按列链接两个矩阵,就是把两矩阵上下相加,要求列数相等。
np.c_是按行链接两个矩阵,就是把两矩阵左右相加,要求行数相等。
hstack和vstack以及concatenate的参数都是tuple,而np.c_和np.r_的调用方式是np.c_[a,b]。
注意:
对于一维数组的链接:结果与二维数组的结果效果不一样
一维数组: e=np.array([1,2,3]) d=np.array([1,2,3]) print(np.vstack((d,e))) print(np.r_[d,e]) 结果: [[1 2 3] [1 2 3]] [1 2 3 1 2 3] print(np.hstack((d,e))) print(np.c_[d,e]) 结果: [1 2 3 1 2 3] [[1 1] [2 2] [3 3]] 二维数组: a=np.array([[1,2,3],[4,5,6]]) b=np.array([[7,8,9],[10,11,12]]) print(np.c_[a,b]) print(np.r_[a,b]) 结果: [[ 1 2 3 7 8 9] [ 4 5 6 10 11 12]] [[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]]
4.将数组进行分割
使用hsplit函数实现横向分割,使用vsplit函数实现纵向分割,使用split函数能够经过设置axis来进行横向和纵向分割(axis=1实现横向分割)。
b=np.array([[7,8,9],[10,11,12]]) 横向分割: np.hsplit(b,3) 等同np.split(b,3,axis=1) 结果: [array([[ 7], [10]]), array([[ 8], [11]]), array([[ 9], [12]])] 纵向分割: np.vsplit(b,2) 等同np.split(b,2,axis=0) 结果: [array([[7, 8, 9]]), array([[10, 11, 12]])]
矩阵是ndarry的子类,矩阵是继承Numpy数组对象的二维数组对象。
建立矩阵:
np.mat('1,2;3,4') np.matrix([[1,2],[3,4]]) 结果: [[1 2] [3 4]]
将二维数组变为矩阵:
np.mat(A)
注:A为二维数组
==注意:==
对于矩阵和二维数组是有区别的,矩阵有一些特殊的属性,H求共轭转置,I求逆矩阵。****对于矩阵而言,求两个矩阵对应元素的乘积只能使用multiply,表明的时矩阵乘积***。
1.经常使用的一些数学函数:
一元:调用形式:np.___(A)
exp():求各元素的指数e^x^ 例如np.exp(A) 会将对应位置变为e^x,x指的是对应位置的元素大小
log10 log2 log1p
log1p指的是log(1+x)
二元:调用形式:np.___(A,B)
maximum minimum 求两个数组,对应位置的最大,最小元素。
还有add subtract multiply divide
例如:
a=np.array([0,1,4,2]) b=np.array([1,2,6,1]) np.maximum(a,b) 结果:[1, 2, 6, 2]
2.数组统计运算:
调用形式:arr.___()
min max sum mean求数组中的最小元素,最大元素,全部的和,平均值
注意:keepdims表示的确保最后返回的数组的维度为(n,1)防止返回一维数组。
例如:
>>> np.sum([[0, 1], [0, 5]], axis=0) array([0, 6]) >>> np.sum([[0, 1], [0, 5]], axis=0,keepdims=True) array([[0, 6]])
argmin argmax 求最小值的索引,求最大值的索引
cumsum 计算元素的累计和(当前位置前面全部元素的和,包括当前位置的元素,相似fibinacci数列)
cumprod 计算元素的累计积,和cumsum的方式相似。
a=np.arange(10) print(a.cumsum()) 结果:[ 0 1 3 6 10 15 21 28 36 45] b=np.array([1,2,0,1]) print(b.cumprod()) 结果:[1, 2, 0, 0]
另外能够在此基础上加上条件表达去达到统计的功能:
例如:
np.mean(pred == Y)*100 计算预测正确率,pred==Y去判断是否相等,bool数组,1表明相等,0表明不相等
3.数组比较运算
返回结果为一个bool型的数组。
a=np.array([1,4,3]) b=np.array([1,3,3]) print(a>b) 结果: [False True False]
4.数组数据处理的相关函数
np.around()函数用于返回五舍六入后的值,可指定精度。
i=np.floor(x)函数用于以元素方式返回输入的下限,取整操做,i<=x。
i=np.ceil(x)函数用于以元素方式返回输入的上限,返回的数值i>=x。
np.where()函数根据 条件从 x 和 y 中选择元素,当为 True 时,选 x,不然选 y。
np.around(round和around相同)
np.around(a, decimals=0, out=None)
对于正好在舍入小数值之间的值,NumPy舍入到最接近的偶数值。当超过5时候(不包含5),才会进位!所以,1.5和2.5轮到2.0,-0.5和0.5轮到0.0等。因为IEEE浮点标准[1]中的小数部分的不精确表示以及当以10的幂进行缩放时引入的偏差,结果也多是使人惊讶的。
参数:
a : array_like。输入数据。
decimals : int,可选。要舍入的小数位数(默认值:0)。若是小数为负数,则指定小数点左侧的位置数。
out : ndarray,可选。替代输出数组,用于放置结果。它必须具备与预期输出相同的形状,但若是须要,将输出输出值的类型。
返回:
rounded_array : ndarray。与a相同类型的数组,包含舍入值。除非指定了out,不然将建立一个新数组。返回对结果的引用。复数的实部和虚部分别舍入。舍入浮点数的结果是浮点数。
例子1:
>>> np.around([0.37, 1.64]) array([ 0., 2.]) >>> np.around([0.37, 1.64], decimals=1) array([ 0.4, 1.6]) >>> np.around([.5, 1.5, 2.5, 3.5, 4.5]) # rounds to nearest even value array([ 0., 2., 2., 4., 4.]) >>> np.around([1,2,3,11], decimals=1) # ndarray of ints is returned array([ 1, 2, 3, 11]) >>> np.around([1,2,3,11], decimals=-1) array([ 0, 0, 0, 10])
经常使用的用法:
np.round(x).astype(int) 将x四舍五入变为整数
np.floor()
>>> a = np.array([-2.5, -1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) >>> np.floor(a) array([-3., -2., -2., -1., 0., 1., 1., 2.])
np.ceil()
>>> a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0]) >>> np.ceil(a) array([-1., -1., -0., 1., 2., 2., 2.])
np.where()
np.where(condition, x, y)
若是只给出条件,则返回condition.nonzero()。
参数:
condition:array_like,bool。若是为True,则产生x,不然产生y。
x,y:array_like,可选。要从中选择的值。x,y和条件须要能够广播broadcastable到某种形状。
返回:
out:ndarray或ndarray元组。若是同时指定了x和y,则输出数组包含x的元素,其中condition为True,其余元素来自 y。若是只给出条件,则返回元组condition.nonzero(),条件为True 的索引。
若是给出x和y而且输入数组是1-D,where则至关于:
[xv if c else yv for (c,xv,yv) in zip(condition,x,y)]
经常使用的例子:
a=np.array([[1,2,3],[4,5,6],[7,8,9]]) b=np.where(a==6) #返回元素为6的行标和列表,返回值为一个元组,第一个为行标,第二个为列标 print(b) print(b[0]) print(b[1]) c=np.where(a[1,:]==5) #在行标为1的条件下,去选择5,返回值为列标的索引 print(c) print(c[0]) #c[0]是一个一维数组 print(c[0][0]) #第一个为5的下标索引 d=np.where(a[1:]==5) #从索引为1的行开始去寻找,此时的行标基于1为0 print(d) 结果: (array([1], dtype=int64), array([2], dtype=int64)) [1] [2] (array([1], dtype=int64),) [1] 1 (array([0], dtype=int64), array([1], dtype=int64))
其余例子:
>>> np.where([[True, False], [True, True]], ... [[1, 2], [3, 4]], ... [[9, 8], [7, 6]]) array([[1, 8], [3, 4]]) >>> np.where([[0, 1], [1, 0]]) (array([0, 1], dtype=int64), array([1, 0], dtype=int64))
>>> x = np.arange(9.).reshape(3, 3) >>> print(x) [[0. 1. 2.] [3. 4. 5.] [6. 7. 8.]] >>> np.where( x > 5 ) (array([2, 2, 2]), array([0, 1, 2])) 元组第一个元素为行标,第二个为列标 >>> x[np.where( x > 3.0 )] # Note: result is 1D. array([ 4., 5., 6., 7., 8.]) >>> np.where(x < 5, x, -1) # Note: broadcasting. array([[ 0., 1., 2.], [ 3., 4., -1.], [-1., -1., -1.]]) >>> goodvalues = [3, 4, 7] >>> ix = np.isin(x, goodvalues) >>> ix array([[False, False, False], [ True, True, False], [False, True, False]]) >>> np.where(ix) (array([1, 1, 2]), array([0, 1, 1]))
对于二进制文件的读写利用load和save,savaz函数.注意对于load读取文件时不能省略扩展名,sava是能够的。save和savez的区别是savez能够存多个数组。
arr=load('data.txt') save('data',arr) savez('data',arr1,arr2) #写进data二进制文件中两个数组 arr=np.load('data.npz') print(arr.files) # 查看各个数组名称 print(arr['arr_0']) #输出第一个数组的内容
下面主要是对文本文件的读写。
从文本文件加载数据到二维数组。
经常使用的参数:
loadtxt(fname,dtype=<class 'float'>,
delimiter=None,usecols=None,unpack=False)
delimiter :间隔符,通常为‘,’
usecols :是一个元组,使用该元组中的元素对应的列。如(0,3)则利用第一列和第四列的数据。
unpack:当是False时,会返回一个数组,当为True时,将该读取的cols的每列分开,返回多个变量,须要多个变量接收。
dataset=np.loadtxt('data1.txt',delimiter=',',usecols=(0,1)) #将第一列和第二列数据加载到dataset数组中
能够将数组写到以某种分隔符隔开的文本文件中。
numpy.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ', encoding=None)
例如: a=np.array([[1,4,3],[2,3,4]]) np.savetxt('data2.txt',a,fmt='%.2f',delimiter=',') 将数组保存到文件中,同时数组元素保留2位小数。若是数组为1维,则会以列的形式保存到文本文件中。
结果:
==注意==:
1.数组进行运算时,结果数组类型遵循向上转换的行为
2.数组太大时,Numpy会自动跳过数组中心部分并仅打印角点,若想打印所有,须要更改打印选项np.set_printoptions(threshold=sys.maxsize)
import sys a=np.arange(10000).reshape(5000,2) print(a) np.set_printoptions(threshold=sys.maxsize) print(a)
可是虽然官方写的是这样,可是用jupyter是不须要更改,显示的是所有数据,用Pycharm须要更改打印选项。
3.‘*’号在Numpy中指的是矢量化运算(按对于元素进行运算),矩阵乘积可使用@运算符或者是dot()函数
4.在编程的过程当中尽可能不使用一维数组防止出错,把一维数组变成行向量和列向量进行处理,对于测试时能够加入assert断言语句。
assert(a.shape==(2,3)) #断言会执行,出错会跳出异常