Python最好用的科學計算庫:NumPy快速入門教程(一)

Python最好用的科學計算庫:NumPy快速入門教程(一)

來自專欄深度學習+自然語言處理(NLP)45 人贊了文章

首先導入並檢查你的numpy版本

import numpynumpy.__version__1.14.3

NumPy數組

NumPy數組指的是由同一類型元素(一般是數字)組成的多維數組。

基礎知識

數組的維度、形狀、大小

一維數組由一個中括弧內的數字組成。

import numpy as np #這裡的一個慣例是使用np作為numpy的別名>>>a = np.array([1,2,3])>>>aarray([1, 2, 3])

二維數組由多個一維數組組成

>>>b = np.array([[1,2,3],[4,5,6],[7,8,9]])>>>barray([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

同理,n維數組由多個n-1維數組組成

>>>c = np.array([[[1,2,1],[1,3,2,]],[[2,2,2],[1,1,1]]])>>>carray([[[1, 2, 1], [1, 3, 2]], [[2, 2, 2], [1, 1, 1]]])

查看數組的維度使用np.ndim

>>>print(數組a的維度是:,a.ndim)>>>print(數組b的維度是:,b.ndim)>>>print(數組c的維度是:,c.ndim)數組a的維度是: 1數組b的維度是: 2數組c的維度是: 3

np.shape:顯示在每個維度里數組的大小,或者說數組的「形狀」。如 n 行 m 列的矩陣,它的 shape 就是(n,m)。

>>>print(數組a的形狀是:,a.shape)>>>print(數組b的形狀是:,b.shape)>>>print(數組c的形狀是:,c.shape)數組a的形狀是: (3,)數組b的形狀是: (3, 3)數組c的形狀是: (2, 2, 3)

np.size:數組中所有元素的總量,相當於數組的 shape 中所有元素的乘積,例如矩陣的元素總量為行與列的乘積。

>>>print(數組a的大小是:,a.size)>>>print(數組b的大小是:,b.size)>>>print(數組c的大小是:,c.size)數組a的大小是: 3數組b的大小是: 9數組c的大小是: 12

數組的元素類型和存儲大小

np.dtype:查看數組中元素的類型。創建數組時,可以指定dtype參數用於創建指定數據類型的數組

>>>a.dtypedtype(int64)>>>d = np.array([1.2, 2.3, 3.4], dtype = np.float)>>>darray([1.2, 2.3, 3.4])

np.itemsize:用於查看數組中元素佔用的位元組,例如,一個元素類型是float64的數組,其中的元素佔用的位元組大小是8(也就是64bit/8)

>>>d.itemsize8

np.data:查看存儲數組的真實內存地址

>>>d.data<memory at 0x10bf10ac8>

創建數組

有很多種方法創建數組。

例如,你可以通過使用數組函數從一個python的列表或元組創建。數組元素的類型由原數據的類型推斷得到。

>>>b = np.array([1.2, 3.5, 5.1])>>>b.dtypedtype(float64)

np.array創建數組時,會將多層嵌套的列錶轉換為多維數組。

>>>b = np.array([(1.5,2,3), (4,5,6)])>>>barray([[1.5, 2. , 3. ], [4. , 5. , 6. ]])

創建數組時我們還可以指定數據類型

>>>c = np.array( [ [1,2], [3,4] ], dtype=complex )#指定數據類型為複數>>>carray([[1.+0.j, 2.+0.j], [3.+0.j, 4.+0.j]])

我們經常遇到這樣的情況,我們並不知道數組的元素,但是知道數組的大小。因此,NumPy提供了多個函數,用於創建有初始數值的佔位數組,這樣可以減少不必要的數組增長及運算成本。

zeros函數創建包含全是0的數組,ones函數創建全是1的數組,empty函數創建一個隨機數值數組,其中的數值由當時的內存狀態決定。這些函數創建的數組的數據類型都是默認的float64.

>>>np.zeros( (3,4) )array([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]])>>>np.ones( (2,3,4), dtype=np.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)>>>np.empty( (2,3) )array([[1.5, 2. , 3. ], [4. , 5. , 6. ]])

為了生成連續的數值,NumPy提供了一個模擬range的函數,不同點是,numpy的range返回的是數組而不是列表

>>>np.arange( 10, 30, 5 ) # 三個參數分別代表起始值10,終止值30,步進5array([10, 15, 20, 25])>>>np.arange( 0, 2, 0.3 )array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])

當 arange 使用浮點型作為參數時,因為浮點精度的有限性,不能預測創建的數組有多少個元素。在這種情況下,換成linspace函數可以更好地確定區間內到底需要產生多少個數組元素。

from numpy import pi>>>np.linspace( 0, 2, 9 ) # 在[0,2]區間內生成9個值array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])

列印數組

當你在屏幕列印一個數組時,NumPy顯示這個數組的方式和嵌套的列表是相似的。但遵守以下布局:

  • 最後一維由左至右列印
  • 倒數第二維從上到下列印
  • 其餘維都是從上到下列印,且通過空行分隔

如下所示,一維數組輸出為一行、二維為矩陣、三維為矩陣列表。

>>>a = np.arange(6) >>>aarray([0, 1, 2, 3, 4, 5])>>>b = np.arange(12).reshape(4,3)>>>aarray([0, 1, 2, 3, 4, 5])>>>c = np.arange(24).reshape(2,3,4)>>>carray([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]])

如果數組太大了,NumPy自動跳過中間的部分不顯示,只顯示兩邊。

>>>print(np.arange(10000))[ 0 1 2 ... 9997 9998 9999]>>>print(np.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]]

如果你想強制輸出所有數據,可以設置set_printoptions參數。

>>>np.set_printoptions(threshold=np.nan)

基本運算

數組中的算術運算一般是元素級的運算,運算結果會產生一個新的數組。

不同於很多矩陣語言,乘積運算操作*在NumPy中是元素級的運算。如果想要進行矩陣運算,可以使用dot函數或方法。

>>>A = np.array( [[1,1],[0,1]] )>>>B = np.array( [[2,0],[3,4]] )>>>A*B# 元素乘積array([[2, 0], [0, 4]])>>>A.dot(B)# 矩陣運算array([[5, 4], [3, 4]])>>>np.dot(A, B)# 另一種方式矩陣運算array([[5, 4], [3, 4]])

一些運算,例如+=*=,會內在的改變一個數組的值,而不是生成一個新的數組。

>>>a = np.ones((2,3), dtype=int)>>>b = np.random.random((2,3))>>>a *= 3>>>aarray([[3, 3, 3], [3, 3, 3]])>>>b += a>>>barray([[3.69902298, 3.1334804 , 3.62673199], [3.37038178, 3.74769131, 3.62235315]])>>>a += b # b不會自動轉換為整型---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-37-175b578703ae> in <module>()----> 1 a += b # b不會自動轉換為整型TypeError: Cannot cast ufunc add output from dtype(float64) to dtype(int64) with casting rule same_kind

當操作不同數據類型的數組時,最後輸出的數組類型一般會與更普遍或更精準的數組相同(這種行為叫做 Upcasting)。

>>>a = np.ones(3, dtype=np.int32)>>>b = np.linspace(0,pi,3)>>>b.dtype.namefloat64>>>c = a+b>>>c.dtype.namefloat64>>>d = np.exp(c*1j)>>>d.dtype.namecomplex128

許多一元運算,如計算數組中所有元素的總和,是屬於 ndarray 類的方法。

>>>a = np.random.random((2,3))>>>aarray([[0.85827711, 0.5385761 , 0.0843277 ], [0.2609027 , 0.36414539, 0.12940627]])>>>a.sum()2.2356352707158513>>>a.min()0.08432769616897462>>>a.max()0.8582771053112916

默認狀態下,這些運算會把數組視為一個數字列表而不關心它的shape。然而,可以指定axis參數針對哪一個維度進行運算。例如axis=0將針對每一個列進行運算。

>>>b = np.arange(12).reshape(3,4)>>>barray([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])>>>b.sum(axis=0)# 列相加array([12, 15, 18, 21])>>>b.min(axis=1) #行相加array([0, 4, 8])>>>b.cumsum(axis=1)#行累加array([[ 0, 1, 3, 6], [ 4, 9, 15, 22], [ 8, 17, 27, 38]])

通用函數

NumPy提供一些熟悉的數學函數,例如sin, cos,和exp等。在NumPy中,這些函數稱為「通用函數」, 這些運算是元素級的,生成一個數組作為結果。

>>>B = np.arange(3)>>>Barray([0, 1, 2])>>>np.exp(B)array([1. , 2.71828183, 7.3890561 ])>>>np.sqrt(B)array([0. , 1. , 1.41421356])>>>C = np.array([2., -1., 4.])>>>np.add(B, C)array([2., 0., 6.])

索引、切片和迭代

一維數組可以索引、切片和迭代,就像列表和其他python數據類型。

>>>a = np.arange(10)**3>>>a[2]8>>>a[2:5]array([ 8, 27, 64])>>>a[:6:2] = -1000 #從0到6,每隔2個設為-1000>>>aarray([-1000, 1, -1000, 27, -1000, 125, 216, 343, 512, 729])>>>a[ : :-1] #翻轉數組aarray([ 729, 512, 343, 216, 125, -1000, 27, -1000, 1, -1000])

多維數組可以每個維度有一個索引值。這些索引值被逗號分開。

>>>def f(x,y):#定義一個函數用於生成數組>>> return 10*x+y>>>b = np.fromfunction(f,(5,4),dtype=int)#利用函數f生成數組,數組的形狀是(5,4),數組中(x,y)的元素值等於 f(x,y)>>>barray([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23], [30, 31, 32, 33], [40, 41, 42, 43]])>>>b[2,3] #第2行,第3列23>>>b[0:5, 1] #等於b[ : ,1] ,第0-5行,第1列array([ 1, 11, 21, 31, 41])>>>b[1:3, : ] #1-3行,所有列array([[10, 11, 12, 13], [20, 21, 22, 23]])

當索引值的數量少於數組的維度時,其他的索引值默認為分號

>>>b[-1] #相當於b[-1,:]array([40, 41, 42, 43])

b[i]中的i代表i後面有足夠多的:,用於表示其他維度的索引。你也可以使用點號...來表示。

點號代表需要的足夠多的列,用於使其他維度的索引值完整。例如,x是一個五維數組,那麼

  • x[1,2,...] 相當於 x[1,2,:,:,:]
  • x[...,3] 相當於 x[:,:,:,:,3]
  • x[4,...,5,:] 相當於 x[4,:,:,5,:]

>>>c = np.array( [[[ 0, 1, 2], #構建一個三維數組 [ 10, 12, 13]], [[100,101,102], [110,112,113]]])>>>c.shape(2, 2, 3)>>>c[1,...]array([[100, 101, 102], [110, 112, 113]])>>>c[...,2]array([[ 2, 13], [102, 113]])

多維數組中的迭代:

>>>for row in b:>>> print(row)[0 1 2 3][10 11 12 13][20 21 22 23][30 31 32 33][40 41 42 43]

但是,如果你想迭代輸出數組中的每一個元素,你可以使用flat屬性實現,這個屬性生成一個可以迭代所有元素的迭代器。

>>>for element in b.flat:>>> print(element)012310111213202122233031323340414243

推薦閱讀:

400行Python實現一個正則++引擎!有興趣?看看我的EasyRegex吧
Flask最佳實踐
Sublime Text 3中怎麼更換python的版本?

TAG:科學計算 | 科技 | Python |