Numpy的使用

1.建立數組

Numpy是在Python中涉及科學計算時確定會用到的,該庫提供多維數組。雖然python含有array數組,可是對於大量數據進行高級數學和其餘類型的操做時,使用Numpy數組比使用array更加有效率,更加簡單。爲何Numpy這麼快,一個很重要的緣由就是矢量化,用近C的速度去作一些運算。(摘自官方文檔)編程

1.1普通建立

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]

1.2建立含初始佔位符的數組

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個元素的等比數列

2.矢量化運算

2.1矢量化

描述了代碼中沒有任何顯示的循環索引等,應用在元素級(即應用與對應元素間的運算)
Numpy中的+-*/都是指的矢量化運算,就是對應位置的元素作加減乘除操做,便再也不贅述。dom

2.2廣播機制

用於描述操做的隱式逐元素行爲的術語,描述瞭如何在算數運算期間處理不一樣形狀的數組,較小的數組在較大的數組上廣播,以便他們具備兼容的形狀,廣播提供了一種矢量化數組操做的辦法。
通常廣播的規則:
從尾尺寸開始,向前發展,當兩個數組的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)

3.索引和切片

3.1索引

基本索引:
對於數組有幾個維度,就至關於有幾個軸,最外層對應軸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]
注意,布爾索引的長度要和二維數組列的元素個數和行的元素個數相同

3.2切片

切片的形式: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]]

4.數組運算

4.1數組部分

對於矩陣運算這部分,由於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]])]

4.2 矩陣部分

矩陣是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,表明的時矩陣乘積***。

5.經常使用函數

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]))

6.讀寫文件

對於二進制文件的讀寫利用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']) #輸出第一個數組的內容

下面主要是對文本文件的讀寫。

6.1loadtxt()

從文本文件加載數據到二維數組。
經常使用的參數:
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數組中

6.2 savetxt()

能夠將數組寫到以某種分隔符隔開的文本文件中。

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))
#斷言會執行,出錯會跳出異常
相關文章
相關標籤/搜索