NumPy簡明教程

源地址:http://blog.csdn.net/sunny2038/article/details/9002531python

http://blog.csdn.net/sunny2038/article/details/9023797數組

http://blog.csdn.net/sunny2038/article/details/8907736dom

NumPy數組(一、數組初探)

更新

目前個人工做是將NumPy引入到Pyston中(一款Dropbox實現的Python編譯器/解釋器)。在工做過程當中,我深刻接觸了NumPy源碼,瞭解其實現並提交了PR修復NumPy的bug。在與NumPy源碼以及NumPy開發者打交道的過程當中,我發現當今中文NumPy教程大部分都是翻譯或參考英文文檔,所以致使了許多疏漏。好比NumPy數組中的broadcast功能,幾乎全部中文文檔都翻譯爲「廣播」。而NumPy的開發者之一,回覆到「broadcast is a compound -- native English speakers can see that it's " broad" + "cast" = "cast (scatter, distribute) broadly, I guess "cast (scatter, distribute) broadly" probably is closer to the meaning(NumPy中的含義)"。有鑑於此,我打算啓動一個項目,以我對NumPy使用以及源碼層面的瞭解編寫一個系列的教程。函數

地址隨後會更新。CSDN的排版(列表)怎麼顯示不正常了。。。佈局

 

NumPy數組

NumPy數組是一個多維數組對象,稱爲ndarray。其由兩部分組成:ui

  • 實際的數據
  • 描述這些數據的元數據

大部分操做僅針對於元數據,而不改變底層實際的數據。編碼

關於NumPy數組有幾點必需瞭解的:spa

  • NumPy數組的下標從0開始。
  • 同一個NumPy數組中全部元素的類型必須是相同的。

NumPy數組屬性

 

在詳細介紹NumPy數組以前。先詳細介紹下NumPy數組的基本屬性。NumPy數組的維數稱爲秩(rank),一維數組的秩爲1,二維數組的秩爲2,以此類推。在NumPy中,每個線性的數組稱爲是一個軸(axes),秩實際上是描述軸的數量。好比說,二維數組至關因而兩個一維數組,其中第一個一維數組中每一個元素又是一個一維數組。因此一維數組就是NumPy中的軸(axes),第一個軸至關因而底層數組,第二個軸是底層數組裏的數組。而軸的數量——秩,就是數組的維數。.net

NumPy的數組中比較重要ndarray對象屬性有:翻譯

  • ndarray.ndim:數組的維數(即數組軸的個數),等於秩。最多見的爲二維數組(矩陣)。

  • ndarray.shape:數組的維度。爲一個表示數組在每一個維度上大小的整數元組。例如二維數組中,表示數組的「行數」和「列數」。ndarray.shape返回一個元組,這個元組的長度就是維度的數目,即ndim屬性。

  • ndarray.size:數組元素的總個數,等於shape屬性中元組元素的乘積。

  • ndarray.dtype:表示數組中元素類型的對象,可以使用標準的Python類型建立或指定dtype。另外也可以使用前一篇文章中介紹的NumPy提供的數據類型。

  • ndarray.itemsize:數組中每一個元素的字節大小。例如,一個元素類型爲float64的數組itemsiz屬性值爲8(float64佔用64個bits,每一個字節長度爲8,因此64/8,佔用8個字節),又如,一個元素類型爲complex32的數組item屬性爲4(32/8)。

  • ndarray.data:包含實際數組元素的緩衝區,因爲通常經過數組的索引獲取元素,因此一般不須要使用這個屬性。

建立數組

  先來介紹建立數組。建立數組的方法有不少。如可使用array函數從常規的Python列表和元組創造數組。所建立的數組類型由原序列中的元素類型推導而來。   
[python] view plain copy
 
  1. >>> from numpy import *  
  2.      
  3. >>> a = array( [2,3,4] )     
  4. >>> a  
  5.     array([2, 3, 4])  
  6. >>> a.dtype  
  7.     dtype('int32')  
  8. >>> b = array([1.2, 3.5, 5.1])     
  9. >>> b.dtype  
  10.     dtype('float64')  

使用array函數建立時,參數必須是由方括號括起來的列表,而不能使用多個數值做爲參數調用array。   

[python]  view plain  copy
 
  1. >>> a = array(1,2,3,4)    # 錯誤  
  2. >>> a = array([1,2,3,4])  # 正確  

可以使用雙重序列來表示二維的數組,三重序列表示三維數組,以此類推。

[python]  view plain  copy
 
  1. >>> b = array( [ (1.5,2,3), (4,5,6) ] )    
  2. >>> b  
  3.     array([[ 1.5,  2. ,  3. ],  
  4.         [ 4. ,  5. ,  6. ]])  

能夠在建立時顯式指定數組中元素的類型

[python]  view plain  copy
 
  1. >>> c = array( [ [1,2], [3,4] ], dtype=complex)  
  2. >>> c  
  3.     array([[ 1.+0.j,  2.+0.j],  
  4.        [ 3.+0.j,  4.+0.j]])  

一般,剛開始時數組的元素未知,而數組的大小已知。所以,NumPy提供了一些使用佔位符建立數組的函數。這些函數有助於知足除了數組擴展的須要,同時下降了高昂的運算開銷。

用函數zeros可建立一個全是0的數組,用函數ones可建立一個全爲1的數組,函數empty建立一個內容隨機而且依賴與內存狀態的數組。默認建立的數組類型(dtype)都是float64。

能夠喲娜特d.dtype.itemsize來查看數組中元素佔用的字節數目。

[python]  view plain  copy
 
  1. >>> d = zeros((3,4))  
  2. >>> d.dtype  
  3. dtype('float64')  
  4. >>> d  
  5. array([[ 0.,  0.,  0.,  0.],  
  6.      [ 0.,  0.,  0.,  0.],  
  7.      [ 0.,  0.,  0.,  0.]])  
  8. >>> d.dtype.itemsize  
  9. 8  

也能夠本身制定數組中元素的類型

[python]  view plain  copy
 
  1. >>> ones( (2,3,4), dtype=int16 )  #手動指定數組中元素類型  
  2.       array([[[1, 1, 1, 1],  
  3.            [1, 1, 1, 1],  
  4.            [1, 1, 1, 1]],  
  5.      
  6.           [[1, 1, 1, 1],  
  7.            [1, 1, 1, 1],  
  8.            [1, 1, 1, 1]]], dtype=int16)  
  9. >>> empty((2,3))  
  10.    array([[  2.65565858e-316,   0.00000000e+000,   0.00000000e+000],  
  11.           [  0.00000000e+000,   0.00000000e+000,   0.00000000e+000]])  

NumPy提供一個相似arange的函數返回一個數列形式的數組:

[python]  view plain  copy
 
  1. >>> arange(10, 30, 5)  
  2.     array([10, 15, 20, 25])  

10開始,差值爲5的等差數列。該函數不只接受整數,還接受浮點參數: 

[python]  view plain  copy
 
  1. >>> arange(0,2,0.5)  
  2.     array([ 0. ,  0.5,  1. ,  1.5])  

arange使用浮點數參數時,因爲浮點數精度有限,一般沒法預測得到的元素個數。所以,最好使用函數linspace去接收咱們想要的元素個數來代替用range來指定步長。linespace用法以下,將在通用函數一節中詳細介紹。

[python]  view plain  copy
 
  1. >>> numpy.linspace(-1, 0, 5)  
  2.         array([-1.  , -0.75, -0.5 , -0.25,  0.  ])  

數組中的元素是經過下標來訪問的,能夠經過方括號括起一個下標來訪問數組中單一一個元素,也能夠以切片的形式訪問數組中多個元素。關於切片訪問,將在切片一節介紹。

 

知識點:NumPy中的數據類型
對於科學計算來講,Python中自帶的整型、浮點型和複數類型遠遠不夠,所以NumPy中添加了許多數據類型。以下:

NumPy中的基本數據類型
名稱 描述
bool 用一個字節存儲的布爾類型(True或False)
inti 由所在平臺決定其大小的整數(通常爲int32或int64)
int8 一個字節大小,-128 至 127
int16 整數,-32768 至 32767
int32 整數,-2 ** 31 至 2 ** 32 -1
int64 整數,-2 ** 63 至 2 ** 63 - 1
uint8 無符號整數,0 至 255
uint16 無符號整數,0 至 65535
uint32 無符號整數,0 至 2 ** 32 - 1
uint64 無符號整數,0 至 2 ** 64 - 1
float16 半精度浮點數:16位,正負號1位,指數5位,精度10位
float32 單精度浮點數:32位,正負號1位,指數8位,精度23位
float64或float 雙精度浮點數:64位,正負號1位,指數11位,精度52位
complex64 複數,分別用兩個32位浮點數表示實部和虛部
complex128或complex 複數,分別用兩個64位浮點數表示實部和虛部

 

NumPy類型轉換方式以下:

[python]  view plain  copy
 
  1. >>> float64(42)  
  2.     42.0  
  3. >>> int8(42.0)  
  4.     42  
  5. >>> bool(42)  
  6.     True  
  7. >>> bool(42.0)  
  8.     True  
  9. >>> float(True)  
  10.     1.0  

許多函數的參數中能夠指定參數的類型,固然,這個類型參數是可選的。以下:

[python]  view plain  copy
 
  1. >>> arange(7, dtype=uint16)  
  2.     array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)  

輸出數組

    當輸出一個數組時,NumPy以特定的佈局用相似嵌套列表的形式顯示:
  • 第一行從左到右輸出
  • 每行依次自上而下輸出
  • 每一個切片經過一個空行與下一個隔開
  • 一維數組被打印成行,二維數組成矩陣,三維數組成矩陣列表。
    
[python] view plain copy
 
  1. >>> a = arange(6)                         # 1d array  
  2. >>> print a  
  3.     [5]  
  4.      
  5. >>> b = arange(12).reshape(4,3)           # 2d array  
  6. >>> print b  
  7.     [[ 0  1  2]  
  8.     [ 3  4  5]  
  9.     [ 6  7  8]  
  10.     [ 10 11]]     
  11. >>> c = arange(24).reshape(2,3,4)         # 3d array  
  12. >>> print c  
  13.     [[[ 0  1  2  3]  
  14.     [ 4  5  6  7]  
  15.     [ 8  10 11]]  
  16.      
  17.     [[12 13 14 15]  
  18.     [16 17 18 19]  
  19.     [20 21 22 23]]]  
    reshape將在下一篇文章中介紹 
若是一個數組太長,則NumPy自動省略中間部分而只打印兩端的數據:   
[python] view plain copy
 
  1. >>> print arange(10000)  
  2.    [   0    1    2 ..., 9997 9998 9999]  
  3.      
  4. >>> print arange(10000).reshape(100,100)  
  5.    [[   0    1    2 ...,   97   98   99]  
  6.     [ 100  101  102 ...,  197  198  199]  
  7.     [ 200  201  202 ...,  297  298  299]  
  8.     ...,  
  9.     [9700 9701 9702 ..., 9797 9798 9799]  
  10.     [9800 9801 9802 ..., 9897 9898 9899]  
  11.     [9900 9901 9902 ..., 9997 9998 9999]]  

  可經過設置printoptions參數來禁用NumPy的這種行爲並強制打印整個數組。

基本運算

數組的算術運算是按元素逐個運算。數組運算後將建立包含運算結果的新數組。

[python]  view plain  copy
 
  1. >>> a= np.array([20,30,40,50])  
  2. >>> b= np.arange( 4)  
  3. >>> b  
  4. array([0, 1, 2, 3])  
  5. >>> c= a-b  
  6. >>> c  
  7. array([20, 29, 38, 47])  
  8. >>> b**2  
  9. array([0, 1, 4, 9])  
  10. >>> 10*np.sin(a)  
  11. array([ 9.12945251,-9.88031624, 7.4511316, -2.62374854])  
  12. >>> a<35  
  13. array([True, True, False, False], dtype=bool)  

與其餘矩陣語言不一樣,NumPy中的乘法運算符*素逐個計算,矩陣乘法可使用dot函數或建立矩陣對象實現(後續章節會介紹)

 

 

[python]  view plain  copy
 
  1. >>> A= np.array([[1,1],  
  2. ...[0,1]])  
  3. >>> B= np.array([[2,0],  
  4. ...[3,4]])  
  5. >>> A*B # 逐個元素相乘  
  6. array([[2, 0],  
  7.        [0, 4]])  
  8. >>> np.dot(A,B) # 矩陣相乘  
  9. array([[5, 4],  
  10.        [3, 4]])  

 

 有些操做符如+=和*=用來更改已存在數組而不建立一個新的數組。

 

[python]  view plain  copy
 
  1. >>> a= np.ones((2,3), dtype=int)  
  2. >>> b= np.random.random((2,3))  
  3. >>> a*= 3  
  4. >>> a  
  5. array([[3, 3, 3],  
  6.        [3, 3, 3]])  
  7. >>> b+= a  
  8. >>> b  
  9. array([[ 3.69092703, 3.8324276, 3.0114541],  
  10.         [ 3.18679111, 3.3039349, 3.37600289]])  
  11. >>> a+= b # b轉換爲整數類型  
  12. >>> a  
  13. array([[6, 6, 6],  
  14.            [6, 6, 6]])  

 

當數組中存儲的是不一樣類型的元素時,數組將使用佔用更多位(bit)的數據類型做爲其自己的數據類型,也就是偏向更精確的數據類型 (這種行爲叫作upcast)。

 

[python]  view plain  copy
 
  1. >>> a= np.ones(3, dtype=np.int32)  
  2. >>> b= np.linspace(0,np.pi,3)  
  3. >>> b.dtype.name  
  4. 'float64'  
  5. >>> c= a+b  
  6. >>> c  
  7. array([ 1., 2.57079633, 4.14159265])  
  8. >>> c.dtype.name  
  9. 'float64'  
  10. >>> d= exp(c*1j)  
  11. >>> d  
  12. array([ 0.54030231+0.84147098j,-0.84147098+0.54030231j,  
  13.         -0.54030231-0.84147098j])  
  14. >>> d.dtype.name  
  15. 'complex128'  

 

  許多非數組運算,如計算數組全部元素之和,都做爲ndarray類的方法來實現,使用時須要用ndarray類的實例來調用這些方法。
[python]  view plain  copy
 
  1. >>> a= np.random.random((2,3))  
  2. >>> a  
  3. array([[ 0.65806048, 0.58216761, 0.59986935],  
  4.            [ 0.6004008, 0.41965453, 0.71487337]])  
  5. >>> a.sum()  
  6.    3.5750261436902333  
  7. >>> a.min()  
  8.      0.41965453489104032  
  9. >>> a.max()  
  10.      0.71487337095581649  
這些運算將數組看做是一維線性列表。但可經過指定axis參數(即數組的行)對指定的軸作相應的運算:

 

[python]  view plain  copy
 
  1. >>> b= np.arange(12).reshape(3,4)  
  2. >>> b  
  3. array([[ 0, 1, 2, 3],  
  4.            [ 4, 5, 6, 7],  
  5.            [ 8, 9, 10, 11]])  
  6. >>> b.sum(axis=0) # 計算每一列的和,注意理解軸的含義,參考數組的第一篇文章  
  7. array([12, 15, 18, 21])  
  8. >>> b.min(axis=1) # 獲取每一行的最小值  
  9. array([0, 4, 8])  
  10. >>> b.cumsum(axis=1) # 計算每一行的累積和  
  11. array([[ 0, 1, 3, 6],  
  12.            [ 4, 9, 15, 22],  
  13.            [ 8, 17, 27, 38]])  

 

索引,切片和迭代

   和列表和其它Python序列同樣,一維數組能夠進行索引、切片和迭代操做。

 

[python]  view plain  copy
 
  1. >>> a= np.arange(10)**#記住,操做符是對數組中逐元素處理的!  
  2. >>> a  
  3. array([0, 1, 8, 27, 64, 125, 216, 343, 512, 729])  
  4. >>> a[2]  
  5. 8  
  6. >>> a[2:5]  
  7. array([ 8, 27, 64])  
  8. >>> a[:6:2]= -1000 # 等同於a[0:6:2]= -1000,從開始到第6個位置,每隔一個元素將其賦值爲-1000  
  9. >>> a  
  10. array([-1000, 1,-1000, 27,-1000, 125, 216, 343, 512, 729])  
  11. >>> a[: :-1] # 反轉a  
  12. array([ 729, 512, 343, 216, 125,-1000, 27,-1000, 1,-1000])  
  13. >>>for i in a:  
  14. ...    print i**(1/3.),  
  15. ...  
  16. nan 1.0 nan 3.0 nan 5.0 6.0 7.0 8.0 9.0  

 

   多維數組能夠每一個軸有一個索引。這些索引由一個逗號分割的元組給出。

 

[python]  view plain  copy
 
  1. >>>def f(x,y):  
  2. ...    return 10*x+y  
  3. ...  
  4. >>> b= np.fromfunction(f,(5,4),dtype=int) #fromfunction是一個函數,下篇文章介紹。  
  5. >>> b  
  6. array([[ 0, 1, 2, 3],  
  7.            [10, 11, 12, 13],  
  8.            [20, 21, 22, 23],  
  9.            [30, 31, 32, 33],  
  10.            [40, 41, 42, 43]])  
  11. >>> b[2,3]  
  12. 23  
  13. >>> b[0:5, 1] # 每行的第二個元素  
  14. array([ 1, 11, 21, 31, 41])  
  15. >>> b[: ,1] # 與前面的效果相同  
  16. array([ 1, 11, 21, 31, 41])  
  17. >>> b[1:3,: ] # 每列的第二和第三個元素  
  18. array([[10, 11, 12, 13],  
  19.            [20, 21, 22, 23]])  

 

   當少於提供的索引數目少於軸數時,已給出的數值按秩的順序複製,確失的索引則默認爲是整個切片:

 

[python]  view plain  copy
 
  1. >>> b[-1] # 最後一行,等同於b[-1,:],-1是第一個軸,而缺失的認爲是:,至關於整個切片。  
  2. array([40, 41, 42, 43])  

 

    b[i]中括號中的表達式被看成i和一系列:,來表明剩下的軸。NumPy也容許你使用「點」像b[i,...]。
    點(…)表明許多產生一個完整的索引元組必要的分號。若是x是秩爲5的數組(即它有5個軸),那麼:   
  • x[1,2,…] 等同於 x[1,2,:,:,:],  
  • x[…,3] 等同於 x[:,:,:,:,3]
  • x[4,…,5,:] 等同 x[4,:,:,5,:] 

 

[python]  view plain  copy
 
  1. >>> c= array( [ [[ 0, 1, 2], #三維數組(兩個2維數組疊加而成)  
  2. ...[ 10, 12, 13]],  
  3. ...  
  4. ...[[100,101,102],  
  5. ...[110,112,113]]] )  
  6. >>> c.shape  
  7.  (2, 2, 3)  
  8. >>> c[1,...] #等同於c[1,:,:]或c[1]  
  9. array([[100, 101, 102],  
  10.            [110, 112, 113]])  
  11. >>> c[...,2] #等同於c[:,:,2]  
  12. array([[ 2, 13],  
  13.            [102, 113]])  

 

多維數組的遍歷是以是第一個軸爲基礎的:

 

[python]  view plain  copy
 
  1. >>>for row in b:  
  2. ...    print row  
  3. ...  
  4. [3]  
  5. [10 11 12 13]  
  6. [20 21 22 23]  
  7. [30 31 32 33]  
  8. [40 41 42 43]  

 

若是想對數組中每一個元素都進行處理,可使用flat屬性,該屬性是一個數組元素迭代器:

 

[python]  view plain  copy
 
  1. >>>for element in b.flat:  
  2. ...    print element,  
  3. ...  
  4. 10 11 12 13 20 21 22 23 30 31 32 33 40 41 42 43  

 

更多關於[]、…、newaxis、ndenumerate、indices、index exp的內容請參考NumPy示例

形狀(shape)操做

更改數組的形狀

數組的形狀取決於其每一個軸上的元素個數:

 

[python]  view plain  copy
 
  1. >>> a= np.floor(10*np.random.random((3,4)))  
  2. >>> a  
  3. array([[ 7., 5., 9., 3.],  
  4.            [ 7., 2., 7., 8.],  
  5.            [ 6., 8., 3., 2.]])  
  6. >>> a.shape  
  7. (3, 4)  

 

能夠用多種方式修改數組的形狀:

 

[python]  view plain  copy
 
  1. >>> a.ravel() # 平坦化數組  
  2. array([ 7., 5., 9., 3., 7., 2., 7., 8., 6., 8., 3., 2.])  
  3. >>> a.shape= (6, 2)  
  4. >>> a.transpose()  
  5. array([[ 7., 9., 7., 7., 6., 3.],  
  6.            [ 5., 3., 2., 8., 8., 2.]])  

 

由ravel()展平的數組元素的順序一般是「C風格」的,就是以行爲基準,最右邊的索引變化得最快,因此元素a[0,0]以後是a[0,1]。若是數組改變成其它形狀(reshape),數組仍然是「C風格」的。NumPy一般建立一個以這個順序保存數據的數組,因此ravel()一般不須要建立起調用數組的副本。但若是數組是經過切片其它數組或有不一樣尋常的選項時,就可能須要建立其副本。還能夠同過一些可選參數函數讓reshape()和ravel()構建FORTRAN風格的數組,即最左邊的索引變化最快。

reshape函數改變調用數組的形狀並返回該數組,而resize函數改變調用數組自身。

 

[python]  view plain  copy
 
  1. >>> a  
  2. array([[ 7., 5.],  
  3.            [ 9., 3.],  
  4.            [ 7., 2.],  
  5.            [ 7., 8.],  
  6.            [ 6., 8.],  
  7.            [ 3., 2.]])  
  8. >>> a.resize((2,6))  
  9. >>> a  
  10. array([[ 7., 5., 9., 3., 7., 2.],  
  11.            [ 7., 8., 6., 8., 3., 2.]])  

 

若是在reshape操做中指定一個維度爲-1,那麼其準確維度將根據實際狀況計算獲得

前兩篇文章對NumPy數組作了基本的介紹,本篇文章對NumPy數組進行較深刻的探討。首先介紹自定義類型的數組,接着數組的組合,最後介紹數組複製方面的問題。

 

自定義結構數組

 

經過NumPy也能夠定義像C語言那樣的結構類型。在NumPy中定義結構的方法以下:

定義結構類型名稱;定義字段名稱,標明字段數據類型。

 

[python]  view plain  copy
 
  1. student= dtype({'names':['name', 'age', 'weight'], 'formats':['S32', 'i','f']}, align = True)  

這裏student是自定義結構類型的名稱,使用dtype函數建立,在第一個參數中,'names'和'formats'不能改變,names中列出的是結構中字段名稱,formats中列出的是對應字段的數據類型。S32表示32字節長度的字符串,i表示32位的整數,f表示32位長度的浮點數。最後一個參數爲True時,表示要求進行內存對齊。

字段中使用NumPy的字符編碼來表示數據類型。更詳細的數據類型見下表。

數據類型 字符編碼
整數 i
無符號整數 u
單精度浮點數 f
雙精度浮點數 d
布爾值 b
複數 D
字符串 S
Unicode U
Void V
在定義好結構類型以後,就能夠定義以該類型爲元素的數組了:

 

 

[python]  view plain  copy
 
  1. a= array([(「Zhang」, 32, 65.5), (「Wang」, 24, 55.2)], dtype =student)  

除了在每一個元素中依次列出對應字段的數據外,還須要在array函數中最後一個參數指定其所對應的數據類型。

注:例子來源於張若愚的Python科學計算藝術的29頁。更多關於dtype的內容請參考《NumPy for Beginner》一書的第二章。

組合函數

這裏介紹以不一樣的方式組合函數。首先建立兩個數組:

[python]  view plain  copy
 
  1. >>> a = arange(9).reshape(3,3)  
  2. >>> a  
  3. array([[0, 1, 2],  
  4.            [3, 4, 5],  
  5.            [6, 7, 8]])  
  6. >>> b = 2 * a  
  7. >>> b  
  8. array([[ 0, 2, 4],  
  9.        [ 6, 8, 10],  
  10.        [12, 14, 16]])  

水平組合

[python]  view plain  copy
 
  1. >>> hstack((a, b))  
  2. array([[ 0, 1, 2, 0, 2, 4],  
  3.        [ 3, 4, 5, 6, 8, 10],  
  4.        [ 6, 7, 8, 12, 14, 16]])  
也可經過concatenate函數並指定相應的軸來得到這一效果:
[python]  view plain  copy
 
  1. >>> concatenate((a, b), axis=1)  
  2. array([[ 0, 1, 2, 0, 2, 4],  
  3.        [ 3, 4, 5, 6, 8, 10],  
  4.        [ 6, 7, 8, 12, 14, 16]])  

垂直組合

[python]  view plain  copy
 
  1. >>> vstack((a, b))  
  2. array([[ 0, 1, 2],  
  3.        [ 3, 4, 5],  
  4.        [ 6, 7, 8],   
  5.        [ 0, 2, 4],  
  6.        [ 6, 8, 10],  
  7.        [12, 14, 16]])  
一樣,可經過concatenate函數,並指定相應的軸來得到這一效果。
[python]  view plain  copy
 
  1. >>> concatenate((a, b), axis=0)  
  2. array([[ 0, 1, 2],  
  3.        [ 3, 4, 5],  
  4.        [ 6, 7, 8],  
  5.        [ 0, 2, 4],  
  6.        [ 6, 8, 10],  
  7.        [12, 14, 16]])  

深度組合

另外,還有深度方面的組合函數dstack。顧名思義,就是在數組的第三個軸(即深度)上組合。以下:

[python]  view plain  copy
 
  1. >>> dstack((a, b))  
  2. array([[[ 0, 0],  
  3.         [ 1, 2],  
  4.         [ 2, 4]],  
  5.   
  6.        [[ 3, 6],  
  7.         [ 4, 8],  
  8.         [ 5, 10]],  
  9.   
  10.        [[ 6, 12],  
  11.         [ 7, 14],  
  12.         [ 8, 16]]])  
仔細觀察,發現對應的元素都組合成一個新的列表,該列表做爲新的數組的元素。

行組合

行組合可將多個一維數組做爲新數組的每一行進行組合:

[python]  view plain  copy
 
  1. >>> one = arange(2)  
  2. >>> one  
  3. array([0, 1])  
  4. >>> two = one + 2  
  5. >>> two  
  6. array([2, 3])  
  7. >>> row_stack((one, two))  
  8. array([[0, 1],  
  9.        [2, 3]])  

對於2維數組,其做用就像垂直組合同樣。

 

列組合

列組合的效果應該很清楚了。以下:

[python]  view plain  copy
 
  1. >>> column_stack((oned, twiceoned))  
  2. array([[0, 2],  
  3.        [1, 3]])  
對於2維數組,其做用就像水平組合同樣。

 

分割數組

在NumPy中,分割數組的函數有hsplit、vsplit、dsplit和split。可將數組分割成相同大小的子數組,或指定原數組分割的位置。

水平分割

[python]  view plain  copy
 
  1. >>> a = arange(9).reshape(3,3)  
  2. >>> a  
  3. array([[0, 1, 2],  
  4.        [3, 4, 5],  
  5.        [6, 7, 8]])  
  6. >>> hsplit(a, 3)  
  7. [array([[0],  
  8.        [3],  
  9.        [6]]),  
  10.  array([[1],  
  11.        [4],  
  12.        [7]]),  
  13.  array([[2],  
  14.        [5],  
  15.        [8]])]  
也調用split函數並指定軸爲1來得到這樣的效果:
[python]  view plain  copy
 
  1. split(a, 3, axis=1)  

垂直分割

垂直分割是沿着垂直的軸切分數組:

[python]  view plain  copy
 
  1. >>> vsplit(a, 3)  
  2. >>> [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]  
一樣,也可經過solit函數並指定軸爲1來得到這樣的效果:
[python]  view plain  copy
 
  1. >>> split(a, 3, axis=0)  

 

面向深度的分割

dsplit函數使用的是面向深度的分割方式:

[python]  view plain  copy
 
  1. >>> c = arange(27).reshape(3, 3, 3)  
  2. >>> c  
  3. array([[[ 0,  1,  2],  
  4.         [ 3,  4,  5],  
  5.         [ 6,  7,  8]],  
  6.   
  7.        [[ 9, 10, 11],  
  8.         [12, 13, 14],  
  9.         [15, 16, 17]],  
  10.   
  11.        [[18, 19, 20],  
  12.         [21, 22, 23],  
  13.         [24, 25, 26]]])  
  14. >>> dsplit(c, 3)  
  15. [array([[[ 0],  
  16.         [ 3],  
  17.         [ 6]],  
  18.   
  19.        [[ 9],  
  20.         [12],  
  21.         [15]],  
  22.   
  23.        [[18],  
  24.         [21],  
  25.         [24]]]),  
  26.  array([[[ 1],  
  27.         [ 4],  
  28.         [ 7]],  
  29.   
  30.        [[10],  
  31.         [13],  
  32.         [16]],  
  33.   
  34.        [[19],  
  35.         [22],  
  36.         [25]]]),  
  37.  array([[[ 2],  
  38.         [ 5],  
  39.         [ 8]],  
  40.   
  41.        [[11],  
  42.         [14],  
  43.         [17]],  
  44.   
  45.        [[20],  
  46.         [23],  
  47.         [26]]])]  

 

複製和鏡像(View)

   當運算和處理數組時,它們的數據有時被拷貝到新的數組有時不是。這一般是新手的困惑之源。這有三種狀況:

徹底不復制

   簡單的賦值,而不復制數組對象或它們的數據。

[python]  view plain  copy
 
  1. >>> a = arange(12)  
  2. >>> b = a      #不建立新對象  
  3. >>> b is a           # a和b是同一個數組對象的兩個名字  
  4. True  
  5. >>> b.shape = 3,4    #也改變了a的形狀  
  6. >>> a.shape  
  7. (3, 4)  

 

    Python 傳遞不定對象做爲參考4,因此函數調用不拷貝數組。

 

[python]  view plain  copy
 
  1. >>> def f(x):  
  2. ...     print id(x)  
  3. ...  
  4. >>> id(a)       #id是一個對象的惟一標識  
  5. 148293216  
  6. >>> f(a)  
  7. 148293216  

 

視圖(view)和淺複製

   不一樣的數組對象分享同一個數據。視圖方法創造一個新的數組對象指向同一數據。

[python]  view plain  copy
 
  1. >>> c = a.view()  
  2. >>> c is a  
  3. False  
  4. >>> c.base is a      #c是a持有數據的鏡像  
  5. True  
  6. >>> c.flags.owndata  
  7. False  
  8. >>>  
  9. >>> c.shape = 2,6    # a的形狀沒變  
  10. >>> a.shape  
  11. (3, 4)  
  12. >>> c[0,4] = 1234        #a的數據改變了  
  13. >>> a  
  14. array([[   0,    1,    2,    3],  
  15.        [1234,    5,    6,    7],  
  16.        [   8,    9,   10,   11]])  
切片數組返回它的一個視圖:
[python]  view plain  copy
 
  1. >>> s = a[ : , 1:3]     # 得到每一行1,2處的元素  
  2. >>> s[:] = 10           # s[:] 是s的鏡像。注意區別s=10 and s[:]=10  
  3. >>> a  
  4. array([[   0,   10,   10,    3],  
  5.        [1234,   10,   10,    7],  
  6.        [   8,   10,   10,   11]])  

 

深複製

   這個複製方法徹底複製數組和它的數據。

[python]  view plain  copy
 
  1. >>> d = a.copy()       #建立了一個含有新數據的新數組對象  
  2. >>> d is a  
  3. False  
  4. >>> d.base is a        #d和a如今沒有任何關係  
  5. False  
  6. >>> d[0,0] = 9999  
  7. >>> a  
  8. array([[   0,   10,   10,    3],  
  9.        [1234,   10,   10,    7],  
  10.        [   8,   10,   10,   11]])  

 

參考文獻: 

《Python科學計算》 
《Tentative NumPy Tutorial》
《NumPy for Beginner》


更多關於shape、reshape、resize和ravel的內容請參考NumPy示例

 
  1. set_printoptions(threshold='nan')  

這樣,輸出時數組的全部元素都會顯示出來。

相關文章
相關標籤/搜索