NumPy-快速處理數據--ndarray對象--數組的創建和存取


本文摘自《用Python做科學計算》,版權歸原作者所有。

NumPy為Python提供了快速的多維數組處理的能力,而SciPy則在NumPy基礎上添加了眾多的科學計算所需的各種工具包,有了這兩個庫,Python就有幾乎和Matlab一樣的處理數據和計算的能力了。可以直接按照書中寫的下載Python(x,y),也可以單獨配置各個模塊。配置方法見:Numpy、SciPy、MatPlotLib在Python2.7.9下的安裝與配置

一、為什么需要Numpy處理數據?

1. 標准安裝的Python中用列表(list)可以用來當作數組使用,但是列表中所保存的是對象(任意對象)的指針。對於數值運算來說這種結構顯然比較浪費內存和CPU計算時間。

2. Python還提供了一個array模塊,array對象和列表不同,它直接保存數值。但是由於它只支持一維數組,也沒有各種運算函數,因此也不適合做數值運算。

NumPy提供了兩種基本的對象,解決標准Python的不足:

  • ndarray(N-dimensional array object)N維數組(簡稱數組)對象,存儲單一數據類型的N維數組
  • ufunc(universal function object)通用函數對象,對數組進行處理的函數。

二、ndarray對象

函數庫導入:

1 import numpy as np#給numpy其一個別名叫np

2.1 創建數組

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM