本文摘自《用Python作科學計算》,版權歸原做者全部。html
NumPy爲Python提供了快速的多維數組處理的能力,而SciPy則在NumPy基礎上添加了衆多的科學計算所需的各類工具包,有了這兩個庫,Python就有幾乎和Matlab同樣的處理數據和計算的能力了。能夠直接按照書中寫的下載Python(x,y),也能夠單獨配置各個模塊。配置方法見:Numpy、SciPy、MatPlotLib在Python2.7.9下的安裝與配置數組
1、爲何須要Numpy處理數據?dom
1. 標準安裝的Python中用列表(list)能夠用來看成數組使用,可是列表中所保存的是對象(任意對象)的指針。對於數值運算來講這種結構顯然比較浪費內存和CPU計算時間。函數
2. Python還提供了一個array模塊,array對象和列表不一樣,它直接保存數值。可是因爲它只支持一維數組,也沒有各類運算函數,所以也不適合作數值運算。工具
NumPy提供了兩種基本的對象,解決標準Python的不足:post
2、ndarray對象url
函數庫導入:spa
1 import numpy as np#給numpy其一個別名叫np
2.1 建立數組.net
2.1.1 建立一維數組:指針
1 a = np.array([1, 2, 3, 4])#方法一,使用列表 2 b = np.array((1, 2, 3, 4))#方法二,只用元組
2.1.2 建立二維數組:
1 c = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])#每一行用中括號括起來
2.1.3 shape屬性獲取數組大小:
1 >>> a.shape 2 (4,) #一個數字表示一維數組 3 >>> c.shape 4 (3, 4) #兩個數字表示二維數組,第0軸長度爲3,第1軸長度爲4
2.1.4 修改shape屬性:
1 >>> c.shape = 4,3 #將數組改成4行3列 2 >>> c #注意不是對數組轉置,只是改變每一個軸的大小,數組元素在內存中的位置並無改變 3 array([[ 1, 2, 3], 4 [ 4, 5, 6], 5 [ 7, 8, 9], 6 [10, 11, 12]]) 7 >>> c.shape 8 (4, 3) 9 >>> c.shape = 2, -1#第二個參數設置爲-1系統會自動計算第二個參數 10 >>> c 11 array([[ 1, 2, 3, 4, 5, 6], 12 [ 7, 8, 9, 10, 11, 12]])
2.1.5 reshape方法,返回一個改變了尺寸的新數組,原數組的shape保持不變:
1 >>> d = a.reshape((2, 2)) 2 >>> d 3 array([[1, 2], 4 [3, 4]]) 5 >>> a 6 array([1, 2, 3, 4]) 7 >>> a[0] = 100 #a和d共享同一塊內存,修改a[0]也會改變d[0, 0] 8 >>> d 9 array([[100, 2], 10 [ 3, 4]])
2.1.6 dtype屬性建立浮點數組,複數數組
1 >>> np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.float)#默認dtype=int32,即默認建立數組元素是整數,而且32位長整型 2 array([[ 1., 2., 3., 4.], 3 [ 5., 6., 7., 8.], 4 [ 9., 10., 11., 12.]]) 5 >>> np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.complex)#建立複數數組 6 array([[ 1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j], 7 [ 5.+0.j, 6.+0.j, 7.+0.j, 8.+0.j], 8 [ 9.+0.j, 10.+0.j, 11.+0.j, 12.+0.j]])
以上介紹的數組建立的方法都是先建立序列,在使用array()函數轉化爲數組,下面介紹使用專門的函數建立數組:
2.1.7 arange(開始值, 終值, 步長):相似Python的range(),注意不包括終值
1 >>> np.arange(0, 1, 0.1)#不包括終值!!! 2 array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
2.1.8 linspace(開始值, 終值, 元素個數): 默認包括終值,能夠使用endpoint設置是否包括終值
1 >>> np.linspace(0, 1, 8)#0~1之間,8個元素 2 array([ 0. , 0.14285714, 0.28571429, 0.42857143, 0.57142857, 3 0.71428571, 0.85714286, 1. ])
2.1.9 logspace(開始值, 終值, 元素個數): 建立等比數列,下面的例子產生1(10^0)到100(10^2)、有10個元素的等比數列:
1 >>> np.logspace(0, 2, 10) 2 array([ 1. , 1.66810054, 2.7825594 , 4.64158883, 3 7.74263683, 12.91549665, 21.5443469 , 35.93813664, 4 59.94842503, 100. ])
2.1.10 fromstring(字符串, dtype=?):從字節建立數組
1 >>> np.fromstring(s, dtype=np.int8)#字符對應的ASCII碼 2 array([ 97, 98, 99, 100, 101, 102, 103], dtype=int8)
2.1.11 fromfunction(計算每一個數組元素的函數, 數組大小即shape)
1 >>> def func1(i): 2 return i%4+1 3 >>> np.fromfunction(func1, (10,))#第二個參數必須是一個序列,本例中用(10,)建立一個10元素的一維數組 4 array([ 1., 2., 3., 4., 1., 2., 3., 4., 1., 2.]) 5 #建立一個二維數組表示九九乘法表 6 >>> def func2(i, j): 7 return (i+1) * (j+1) 8 >>> np.fromfunction(func2, (9, 9)) 9 array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9.], 10 [ 2., 4., 6., 8., 10., 12., 14., 16., 18.], 11 [ 3., 6., 9., 12., 15., 18., 21., 24., 27.], 12 [ 4., 8., 12., 16., 20., 24., 28., 32., 36.], 13 [ 5., 10., 15., 20., 25., 30., 35., 40., 45.], 14 [ 6., 12., 18., 24., 30., 36., 42., 48., 54.], 15 [ 7., 14., 21., 28., 35., 42., 49., 56., 63.], 16 [ 8., 16., 24., 32., 40., 48., 56., 64., 72.], 17 [ 9., 18., 27., 36., 45., 54., 63., 72., 81.]])
2.2 存取元素
2.2.1 數組的存取方法與Python的標準方法相同
1 >>> a = np.arange(10) 2 >>> a[5] # 用整數做爲下標能夠獲取數組中的某個元素 3 5 4 >>> a[3:5] # 用範圍做爲下標獲取數組的一個切片,包括a[3]不包括a[5] 5 array([3, 4]) 6 >>> a[:5] # 省略開始下標,表示從a[0]開始 7 array([0, 1, 2, 3, 4]) 8 >>> a[:-1] # 下標能夠使用負數,表示從數組後往前數 9 array([0, 1, 2, 3, 4, 5, 6, 7, 8]) 10 >>> a[2:4] = 100,101 # 下標還能夠用來修改元素的值 11 >>> a 12 array([ 0, 1, 100, 101, 4, 5, 6, 7, 8, 9]) 13 >>> a[1:-1:2] # 範圍中的第三個參數表示步長,2表示隔一個元素取一個元素 14 array([ 1, 101, 5, 7]) 15 >>> a[::-1] # 省略範圍的開始下標和結束下標,步長爲-1,整個數組頭尾顛倒 16 array([ 9, 8, 7, 6, 5, 4, 101, 100, 1, 0]) 17 >>> a[5:1:-2] # 步長爲負數時,開始下標必須大於結束下標 18 array([ 5, 101])
和Python的列表序列不一樣,經過下標範圍獲取的新的數組是原始數組的一個視圖。它與原始數組共享同一塊數據空間:
1 >>> b = a[3:7] # 經過下標範圍產生一個新的數組b,b和a共享同一塊數據空間 2 >>> b 3 array([101, 4, 5, 6]) 4 >>> b[2] = -10 # 將b的第2個元素修改成-10 5 >>> b 6 array([101, 4, -10, 6]) 7 >>> a # a的第5個元素也被修改成10 8 array([ 0, 1, 100, 101, 4, -10, 6, 7, 8, 9])
除了使用下表範圍存取元素以外,NumPy還提供了兩種存取元素的高級方法。
2.2.2 使用整數序列
當使用整數序列對數組元素進行存取時,將使用整數序列中的每一個元素做爲下標,整數序列能夠是列表(如第4行)或者數組(如第6行)。使用整數序列做爲下標得到的數組不和原始數組共享數據空間。
1 >>> x = np.arange(10,1,-1) 2 >>> x 3 array([10, 9, 8, 7, 6, 5, 4, 3, 2]) 4 >>> x[[3, 3, 1, 8]] # 獲取x中的下標爲3, 3, 1, 8的4個元素,組成一個新的數組 5 array([7, 7, 9, 2]) 6 >>> b = x[np.array([3,3,-3,8])] #np.array(序列)做用是將序列轉化爲數組,下標能夠是負數 7 >>> b[2] = 100 8 >>> b 9 array([7, 7, 100, 2]) 10 >>> x # 因爲b和x不共享數據空間,所以x中的值並無改變 11 array([10, 9, 8, 7, 6, 5, 4, 3, 2]) 12 >>> x[[3,5,1]] = -1, -2, -3 # 整數序列下標也能夠用來修改元素的值 13 >>> x 14 array([10, -3, 8, -1, 6, -2, 4, 3, 2])
2.2.3 使用布爾數組
當使用布爾數組b做爲下標存取數組x中的元素時,將收集數組x中全部在數組b中對應下標爲True的元素。使用布爾數組做爲下標得到的數組不和原始數組共享數據空間,注意這種方式只對應於布爾數組,不能使用布爾列表。
1 >>> x = np.arange(5,0,-1) 2 >>> x 3 array([5, 4, 3, 2, 1]) 4 >>> x[np.array([True, False, True, False, False])] 5 >>> # 下標爲True的取出來,布爾數組中下標爲0,2的元素爲True,所以獲取x中下標爲0,2的元素 6 array([5, 3]) 7 >>> x[[True, False, True, False, False]]#Error,這不是咱們想要的結果 8 >>> # 若是是布爾列表,則把True看成1, False看成0,按照整數序列方式獲取x中的元素 9 array([4, 5, 4, 5, 5]) 10 >>> x[np.array([True, False, True, True])] 11 >>> # 布爾數組的長度不夠時,不夠的部分都看成False 12 array([5, 3, 2]) 13 >>> x[np.array([True, False, True, True])] = -1, -2, -3#只修改下標爲True的元素 14 >>> # 布爾數組下標也能夠用來修改元素 15 >>> x 16 array([-1, 4, -2, -3, 1])
布爾數組通常不是手工產生,而是使用布爾運算的ufunc函數產生,關於ufunc函數請參照 ufunc運算 一節。
1 >>> x = np.random.rand(10) # 產生一個長度爲10,元素值爲0-1的隨機數的數組 2 >>> x 3 array([ 0.72223939, 0.921226 , 0.7770805 , 0.2055047 , 0.17567449, 4 0.95799412, 0.12015178, 0.7627083 , 0.43260184, 0.91379859]) 5 >>> x>0.5 6 >>> # 數組x中的每一個元素和0.5進行大小比較,獲得一個布爾數組,True表示x中對應的值大於0.5 7 array([ True, True, True, False, False, True, False, True, False, True], dtype=bool) 8 >>> x[x>0.5]# x>0.5是一個布爾數組 9 >>> # 使用x>0.5返回的布爾數組收集x中的元素,所以獲得的結果是x中全部大於0.5的元素的數組 10 array([ 0.72223939, 0.921226 , 0.7770805 , 0.95799412, 0.7627083 , 11 0.91379859])