源地址:http://blog.csdn.net/sunny2038/article/details/9002531
http://blog.csdn.net/sunny2038/article/details/9023797
http://blog.csdn.net/sunny2038/article/details/8907736
NumPy數組(1、數組初探)
更新
目前我的工作是將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。其由兩部分組成:
- 實際的數據
- 描述這些數據的元數據
大部分操作僅針對於元數據,而不改變底層實際的數據。
關於NumPy數組有幾點必需了解的:
- NumPy數組的下標從0開始。
- 同一個NumPy數組中所有元素的類型必須是相同的。
NumPy數組屬性
在詳細介紹NumPy數組之前。先詳細介紹下NumPy數組的基本屬性。NumPy數組的維數稱為秩(rank),一維數組的秩為1,二維數組的秩為2,以此類推。在NumPy中,每一個線性的數組稱為是一個軸(axes),秩其實是描述軸的數量。比如說,二維數組相當於是兩個一維數組,其中第一個一維數組中每個元素又是一個一維數組。所以一維數組就是NumPy中的軸(axes),第一個軸相當於是底層數組,第二個軸是底層數組里的數組。而軸的數量——秩,就是數組的維數。
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列表和元組創造數組。所創建的數組類型由原序列中的元素類型推導而來。
- >>> from numpy import *
- >>> a = array( [2,3,4] )
- >>> a
- array([2, 3, 4])
- >>> a.dtype
- dtype('int32')
- >>> b = array([1.2, 3.5, 5.1])
- >>> b.dtype
- dtype('float64')
使用array函數創建時,參數必須是由方括號括起來的列表,而不能使用多個數值作為參數調用array。
- >>> a = array(1,2,3,4) # 錯誤
- >>> a = array([1,2,3,4]) # 正確
可使用雙重序列來表示二維的數組,三重序列表示三維數組,以此類推。
- >>> b = array( [ (1.5,2,3), (4,5,6) ] )
- >>> b
- array([[ 1.5, 2. , 3. ],
- [ 4. , 5. , 6. ]])
可以在創建時顯式指定數組中元素的類型
- >>> c = array( [ [1,2], [3,4] ], dtype=complex)
- >>> c
- array([[ 1.+0.j, 2.+0.j],
- [ 3.+0.j, 4.+0.j]])
通常,剛開始時數組的元素未知,而數組的大小已知。因此,NumPy提供了一些使用占位符創建數組的函數。這些函數有助於滿足除了數組擴展的需要,同時降低了高昂的運算開銷。
用函數zeros可創建一個全是0的數組,用函數ones可創建一個全為1的數組,函數empty創建一個內容隨機並且依賴與內存狀態的數組。默認創建的數組類型(dtype)都是float64。
可以喲娜特d.dtype.itemsize來查看數組中元素占用的字節數目。
- >>> d = zeros((3,4))
- >>> d.dtype
- dtype('float64')
- >>> d
- array([[ 0., 0., 0., 0.],
- [ 0., 0., 0., 0.],
- [ 0., 0., 0., 0.]])
- >>> d.dtype.itemsize
- 8
也可以自己制定數組中元素的類型
- >>> ones( (2,3,4), dtype=int16 ) #手動指定數組中元素類型
- array([[[1, 1, 1, 1],
- [1, 1, 1, 1],
- [1, 1, 1, 1]],
- [[1, 1, 1, 1],
- [1, 1, 1, 1],
- [1, 1, 1, 1]]], dtype=int16)
- >>> empty((2,3))
- array([[ 2.65565858e-316, 0.00000000e+000, 0.00000000e+000],
- [ 0.00000000e+000, 0.00000000e+000, 0.00000000e+000]])
NumPy提供一個類似arange的函數返回一個數列形式的數組:
- >>> arange(10, 30, 5)
- array([10, 15, 20, 25])
以10開始,差值為5的等差數列。該函數不僅接受整數,還接受浮點參數:
- >>> arange(0,2,0.5)
- array([ 0. , 0.5, 1. , 1.5])
當arange使用浮點數參數時,由於浮點數精度有限,通常無法預測獲得的元素個數。因此,最好使用函數linspace去接收我們想要的元素個數來代替用range來指定步長。linespace用法如下,將在通用函數一節中詳細介紹。
- >>> numpy.linspace(-1, 0, 5)
- array([-1. , -0.75, -0.5 , -0.25, 0. ])
數組中的元素是通過下標來訪問的,可以通過方括號括起一個下標來訪問數組中單一一個元素,也可以以切片的形式訪問數組中多個元素。關於切片訪問,將在切片一節介紹。
知識點:NumPy中的數據類型
對於科學計算來說,Python中自帶的整型、浮點型和復數類型遠遠不夠,因此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類型轉換方式如下:
- >>> float64(42)
- 42.0
- >>> int8(42.0)
- 42
- >>> bool(42)
- True
- >>> bool(42.0)
- True
- >>> float(True)
- 1.0
許多函數的參數中可以指定參數的類型,當然,這個類型參數是可選的。如下:
- >>> arange(7, dtype=uint16)
- array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)
輸出數組
當輸出一個數組時,NumPy以特定的布局用類似嵌套列表的形式顯示:
- 第一行從左到右輸出
- 每行依次自上而下輸出
- 每個切片通過一個空行與下一個隔開
- 一維數組被打印成行,二維數組成矩陣,三維數組成矩陣列表。
- >>> a = arange(6) # 1d array
- >>> print a
- [0 1 2 3 4 5]
- >>> b = arange(12).reshape(4,3) # 2d array
- >>> print b
- [[ 0 1 2]
- [ 3 4 5]
- [ 6 7 8]
- [ 9 10 11]]
- >>> c = arange(24).reshape(2,3,4) # 3d array
- >>> print c
- [[[ 0 1 2 3]
- [ 4 5 6 7]
- [ 8 9 10 11]]
- [[12 13 14 15]
- [16 17 18 19]
- [20 21 22 23]]]
reshape將在下一篇文章中介紹
如果一個數組太長,則NumPy自動省略中間部分而只打印兩端的數據:
- >>> print arange(10000)
- [ 0 1 2 ..., 9997 9998 9999]
- >>> print arange(10000).reshape(100,100)
- [[ 0 1 2 ..., 97 98 99]
- [ 100 101 102 ..., 197 198 199]
- [ 200 201 202 ..., 297 298 299]
- ...,
- [9700 9701 9702 ..., 9797 9798 9799]
- [9800 9801 9802 ..., 9897 9898 9899]
- [9900 9901 9902 ..., 9997 9998 9999]]
可通過設置printoptions參數來禁用NumPy的這種行為並強制打印整個數組。
- set_printoptions(threshold='nan')
這樣,輸出時數組的所有元素都會顯示出來。
