目錄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)) #斷言會執行,出錯會跳出異常