numpy快速入門(一)
numpy快速入門(一)
原文連結
NUMPY簡介
NumPy是使用Python進行科學計算的基礎包。它包含如下內容:
- 一個強大的N維陣列物件
- 複雜的(廣播)功能
- 用於整合C / C ++和Fortran程式碼的工具
- 有用的線性代數,傅立葉變換和隨機數功能
除了明顯的科學用途外,NumPy還可以用作通用資料的高效多維容器。可以定義任意資料型別。這使NumPy能夠無縫快速地與各種資料庫整合。
安裝方式
安裝方式有很多種,比如通過原始碼安裝,通過wheel檔案安裝等,其實最方便最常用的還是通過pip安裝:
pip install numpy
新手入門
入門條件
在閱讀本教程之前,您應該瞭解一些Python。如果您想重溫記憶,請檢視Python教程。
如果您希望使用本教程中的示例,則還必須在計算機上安裝某些軟體。有關說明,請參閱 http://scipy.org/install.html。
基礎知識
NumPy的主要物件是同構多維陣列。它是一個元素表(通常是數字),都是相同的型別,由正整數元組索引。在NumPy維度中稱為軸。
例如,3D空間中的點的座標[1, 2, 1]具有一個軸。該軸有3個元素,所以我們說它的長度為3.在下面所示的例子中,陣列有2個軸。第一軸的長度為2,第二軸的長度為3。
import numpy as np a=np.array([ [1,2,3], [4,5,6] ]) print('第一個軸的長度是:{}'.format(len(a))) print('第二個軸的長度是:{}'.format(len(a[0])))
第一個軸的長度是:2
第二個軸的長度是:3
numpy的陣列類是ndarray,它的別名是array。請注意,numpy.array這與標準Python庫類array.array不同,後者僅處理一維陣列並提供較少的功能。ndarray物件更重要的屬性是:
ndarray.ndim
陣列的軸(維度)的個數。在Python世界中,維度的數量被稱為rank。
ndarray.shape
陣列的維度。這是一個整數的元組,表示每個維度中陣列的大小。對於有n行和m列的矩陣,shape將是(n,m)。因此,shape元組的長度就是rank或維度的個數 ndim。
ndarray.size
陣列元素的總數。這等於shape的元素的乘積。
ndarray.dtype
一個描述陣列中元素型別的物件。可以使用標準的Python型別建立或指定dtype。另外NumPy提供它自己的型別。例如numpy.int32、numpy.int16和numpy.float64。
ndarray.itemsize
陣列中每個元素的位元組大小。例如,元素為 float64 型別的陣列的 itemsize 為8(=64/8),而 complex32 型別的陣列的 itemsize 為4(=32/8)。它等於 ndarray.dtype.itemsize 。
ndarray.data
該緩衝區包含陣列的實際元素。通常,我們不需要使用此屬性,因為我們將使用索引訪問陣列中的元素。
下面舉了兩個例子,注意對比理解屬性的變化
import numpy as np
a=np.array([
[1,2,3],
[4,5,6]
])
print('ndarray.ndim:',a.ndim)
print('ndarray.shape:',a.shape)
print('ndarray.size:',a.size)
print('ndarray.dtype:',a.dtype)
print('ndarray.itemsize:',a.itemsize)
ndarray.ndim: 2
ndarray.shape: (2, 3)
ndarray.size: 6
ndarray.dtype: int32
ndarray.itemsize: 4
import numpy as np
a=np.arange(32).reshape(4,4,2)
print(a)
print('ndarray.ndim:',a.ndim)
print('ndarray.shape:',a.shape)
print('ndarray.size:',a.size)
print('ndarray.dtype:',a.dtype)
print('ndarray.itemsize:',a.itemsize)
[[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]]
[[ 8 9]
[10 11]
[12 13]
[14 15]]
[[16 17]
[18 19]
[20 21]
[22 23]]
[[24 25]
[26 27]
[28 29]
[30 31]]]
ndarray.ndim: 3
ndarray.shape: (4, 4, 2)
ndarray.size: 32
ndarray.dtype: int32
ndarray.itemsize: 4
陣列的建立
有幾種建立陣列的方法。例如,你可以使用array函式從常規Python列表或元組中建立陣列。得到的陣列的型別是從Python列表中元素的型別推匯出來的。
從python資料中建立
import numpy as np
a=np.array([1,2,3,4,5])
print('a is :',a)
print('a\'s type is :',type(a))
print('a\'s dtype is :',a.dtype)
a is : [1 2 3 4 5]
a's type is : <class 'numpy.ndarray'>
a's dtype is : int32
一個常見的錯誤在於使用多個數值引數呼叫 array 函式,而不是提供一個數字列表(List)作為引數。
a = np.array(1,2,3,4) # WRONG
a = np.array([1,2,3,4]) # RIGHT
用numpy生成佔位符
通常,陣列的元素最初是未知的,但它的大小是已知的。因此,NumPy提供了幾個函式來建立具有初始佔位符內容的陣列。這就減少了陣列增長的必要,因為陣列增長的操作花費很大。
函式 zeros 建立一個由0組成的陣列,函式 ones 建立一個由1陣列的陣列,函式 empty 內容是隨機的並且取決於儲存器的狀態。預設情況下,建立的陣列的dtype是 float64。
import numpy as np
a=np.zeros((4,2))
b=np.ones((4,2))
c=np.empty((4,2))
print('result of np.zeros((4,2)) is :\n',a,'\n')
print('result of np.ones((4,2)) is :\n',b,'\n')
print('result of np.empty((4,2)) is :\n',c,'\n')
result of np.zeros((4,2)) is :
[[0. 0.]
[0. 0.]
[0. 0.]
[0. 0.]]
result of np.ones((4,2)) is :
[[1. 1.]
[1. 1.]
[1. 1.]
[1. 1.]]
result of np.empty((4,2)) is :
[[0.00000000e+000 0.00000000e+000]
[0.00000000e+000 0.00000000e+000]
[0.00000000e+000 6.18570189e-321]
[3.11510340e-307 3.11521375e-307]]
使用arange函式建立
要建立數字序列,NumPy提供了一個類似於 range 的函式,該函式返回陣列而不是列表。
import numpy as np
a=np.arange(10,30,5)#10代表起始數,30代表終止數,5代表步長
print('a is :',a)
print('a\'s type is :',type(a))
print('a\'s dtype is :',a.dtype)
a is : [10 15 20 25]
a's type is : <class 'numpy.ndarray'>
a's dtype is : int32
當 arange 與浮點引數一起使用時,由於浮點數的精度是有限的,通常不可能預測獲得的元素數量。出於這個原因,通常最好使用函式 linspace ,它接收我們想要的元素數量而不是步長作為引數:
from numpy import pi
a=np.linspace(0,2,9)#從0到2之間取9個數
b=np.linspace( 0, 2*pi, 10 )# 在取值數量很多時適用
c=np.sin(b)
print('a is :\n',a,'\n')
print('a\'s type is :',type(a),'\n')
print('a\'s dtype is :',a.dtype,'\n')
print('b is :\n',b,'\n')
print('b\'s type is :',type(b),'\n')
print('b\'s dtype is :',b.dtype,'\n')
print('c is :\n',c,'\n')
print('c\'s type is :',type(c),'\n')
print('c\'s dtype is :',c.dtype,'\n')
a is :
[0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. ]
a's type is : <class 'numpy.ndarray'>
a's dtype is : float64
b is :
[0. 0.6981317 1.3962634 2.0943951 2.7925268 3.4906585
4.1887902 4.88692191 5.58505361 6.28318531]
b's type is : <class 'numpy.ndarray'>
b's dtype is : float64
c is :
[ 0.00000000e+00 6.42787610e-01 9.84807753e-01 8.66025404e-01
3.42020143e-01 -3.42020143e-01 -8.66025404e-01 -9.84807753e-01
-6.42787610e-01 -2.44929360e-16]
c's type is : <class 'numpy.ndarray'>
c's dtype is : float64
另見:
array, zeros, zeros_like, ones, ones_like, empty, empty_like, arange, linspace, numpy.random.rand, numpy.random.randn, fromfunction, fromfile
列印陣列
當你列印陣列時,NumPy以與巢狀列表類似的方式顯示它,但是具有以下佈局:
- 最後一個軸從左到右列印,
- 倒數第二個從上到下列印,
- 其餘的也從上到下列印,每個切片與下一個用空行分開。
一維陣列被列印為行、二維為矩陣和三維為矩陣列表。
a = np.arange(6)
print('一維列印')
print(a)#一維列印
b = np.arange(12).reshape(4,3)
print('二維列印')
print(b)#二維列印
c = np.arange(24).reshape(2,3,4)
print('三維列印')
print(c)#三維列印
一維列印
[0 1 2 3 4 5]
二維列印
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
三維列印
[[[ 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))
print(np.arange(10000).reshape(100,100))
[ 0 1 2 ... 9997 9998 9999]
[[ 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]]
#要禁用此行為並強制NumPy列印整個陣列,你可以使用 set_printoptions 更改列印選項。
np.set_printoptions(threshold=np.nan)
基本操作
在陣列元素上進行數學運算,產生新的陣列。
import numpy as np
a=np.array([1,2,3,4])
b=np.arange(4)
c=a-b
d=a**2
e=10*np.sin(a)
f=a<3
print('a is:\n',a,'\n')
print('b is:\n',b,'\n')
print('c(a-b) is:\n',c,'\n')
print('d(a**2) is:\n',d,'\n')
print('e(10*np.sin(a)) is:\n',e,'\n')
print('c(a<3) is:\n',f,'\n')
a is:
[1 2 3 4]
b is:
[0 1 2 3]
c(a-b) is:
[1 1 1 1]
d(a**2) is:
[ 1 4 9 16]
e(10*np.sin(a)) is:
[ 8.41470985 9.09297427 1.41120008 -7.56802495]
c(a<3) is:
[ True True False False]
與許多矩陣語言不同,乘法運算子 * 的運算在NumPy陣列中是元素級別的,也稱為哈達馬積。矩陣乘積可以使用@運算子(在python> = 3.5中)或dot函式或方法執行:
a=np.array( [[1,1],[0,1]])
b=np.array( [[2,0],[3,4]])
c=a*b#元素乘積
[email protected]#矩陣乘積
e=a.dot(b)#另一種矩陣乘積的方式
print('a is:\n',a,'\n')
print('b is:\n',b,'\n')
print('c(a*b) is:\n',c,'\n')
print('d([email protected]) is:\n',d,'\n')
print('e(a.dot(b)) is:\n',e,'\n')
a is:
[[1 1]
[0 1]]
b is:
[[2 0]
[3 4]]
c(a*b) is:
[[2 0]
[0 4]]
d([email protected]) is:
[[5 4]
[3 4]]
e(a.dot(b)) is:
[[5 4]
[3 4]]
某些操作(例如+=和*=)適用於修改現有陣列,而不是建立新陣列。
a = np.ones((2,3), dtype=int)
print('a is :\n',a,'\n')
a *= 3
print('a *= 3 is :\n',a,'\n')
b = np.random.random((2,3))
print('b is :\n',b,'\n')
b +=a
print('b +=a is :\n',b,'\n')
a += b # b不會自動轉換成int型別,會報錯
a is :
[[1 1 1]
[1 1 1]]
a *= 3 is :
[[3 3 3]
[3 3 3]]
b is :
[[0.49859704 0.93300205 0.03490493]
[0.04724951 0.45715042 0.38407476]]
b +=a is :
[[3.49859704 3.93300205 3.03490493]
[3.04724951 3.45715042 3.38407476]]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-26-b1ab720e80e5> in <module>
8 print('b +=a is :\n',b,'\n')
9
---> 10 a += b # b不會自動轉換成int型別,會報錯
TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind'
當使用不同型別的陣列操作時,結果陣列的型別對應於更一般或更精確的陣列(稱為向上轉換的行為)。
a = np.ones(3, dtype=np.int32)
b = np.linspace(0,pi,3)
c = a+b
d = np.exp(c*1j)
print('a.dtype.name is ',a.dtype.name)
print('b.dtype.name is ',b.dtype.name)
print('c.dtype.name is ',c.dtype.name)
print('d.dtype.name is ',d.dtype.name)
a.dtype.name is int32
b.dtype.name is float64
c.dtype.name is float64
d.dtype.name is complex128
許多一元運算,例如計算陣列中所有元素的總和,都是作為 ndarray 類的方法實現的。
a = np.random.random((2,3))
sum=a.sum()
min=a.min()
max=a.max()
print('a is:\n ',a,'\n')
print('sum(a.sum()) is:\n',sum,'\n')
print('min(a.min()) is:\n',min,'\n')
print('max(a.max()) is:\n',max,'\n')
a is:
[[0.50477827 0.7117427 0.02840961]
[0.96608057 0.02399329 0.67794353]]
sum(a.sum()) is:
2.9129479747742897
min(a.min()) is:
0.02399329487095969
max(a.max()) is:
0.9660805718319886
預設情況下,這些操作適用於陣列,就好像它是數字列表一樣,無論其形狀如何。但是,通過指定 axis 引數,你可以沿著陣列的指定軸應用操作:
a = np.arange(12).reshape(3,4)
sum=a.sum(axis=0)# sum of each column
min=a.min(axis=1) # min of each row
cumsum=a.cumsum(axis=1)# cumulative sum along each row
print('a is:\n ',a,'\n')
print('sum(a.sum()) is:\n',sum,'\n')
print('min(a.min()) is:\n',min,'\n')
print('cumsum(a.cumsum()) is:\n',cumsum,'\n')
a is:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
sum(a.sum()) is:
[12 15 18 21]
min(a.min()) is:
[0 4 8]
cumsum(a.cumsum()) is:
[[ 0 1 3 6]
[ 4 9 15 22]
[ 8 17 27 38]]
通用函式
NumPy提供熟悉的數學函式,例如sin,cos和exp。在NumPy中,這些被稱為“通用函式”(ufunc)。在NumPy中,這些函式在陣列上以元素方式執行,產生一個數組作為輸出。
a=np.arange(3)
b=np.exp(a)
c=np.sqrt(a)
print('a is:\n ',a,'\n')
print('b is:\n ',b,'\n')
print('c is:\n ',c,'\n')
a is:
[0 1 2]
b is:
[1. 2.71828183 7.3890561 ]
c is:
[0. 1. 1.41421356]
另請參見:
all, any, apply_along_axis, argmax, argmin, argsort, average, bincount, ceil, clip, conj, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, inv, lexsort, max, maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sort, std, sum, trace, transpose, var, vdot, vectorize, where
索引、切片和迭代
一維陣列可以被索引,切片和迭代,就像列出和其他Python序列一樣。
a = np.arange(10)**3
print('a is:\n ',a,'\n')
print('a[2] is:',a[2],'\n')
print('a[2:5] is:',a[2:5],'\n')
a[:6:2] = -1000# equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
print('a is:\n ',a,'\n')
print('a[ : :-1] is:\n ',a[ : :-1],'\n')#倒排a
for i in a:
print(i**(1/3.))#由於jupyter的原因,這裡報錯了
a is:
[ 0 1 8 27 64 125 216 343 512 729]
a[2] is: 8
a[2:5] is: [ 8 27 64]
a is:
[-1000 1 -1000 27 -1000 125 216 343 512 729]
a[ : :-1] is:
[ 729 512 343 216 125 -1000 27 -1000 1 -1000]
nan
1.0
nan
3.0
nan
5.0
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998
d:\testproj\test_python\zhyblog\venv\lib\site-packages\ipykernel_launcher.py:9: RuntimeWarning: invalid value encountered in power
if __name__ == '__main__':
多維(Multidimensional) 陣列每個軸可以有一個索引。 這些索在元組中以逗號分隔給出:
def f(x,y):
return 10*x+y
a = np.fromfunction(f,(5,4),dtype=int)
print('a is:\n ',a,'\n')
print('a[2,3] is ',a[2,3])
print('a[0:5,1] is ',a[0:5,1])# each row in the second column of a
print('a[ : ,1] is ',a[ : ,1]) # equivalent to the previous example
print('a[1:3, : ] is \n',a[1:3, : ])# each column in the second and third row of b
a is:
[[ 0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]]
a[2,3] is 23
a[0:5,1] is [ 1 11 21 31 41]
a[ : ,1] is [ 1 11 21 31 41]
a[1:3, : ] is
[[10 11 12 13]
[20 21 22 23]]
當提供比軸數更少的索引時,缺失的索引被認為是一個完整切片 :
a[-1]
array([40, 41, 42, 43])
b[i] 方括號中的表示式 i 被視為後面緊跟著 : 的多個例項,用於表示剩餘軸。NumPy也允許你使用三個點寫為 b[i,...]。
三個點( ... )表示產生完整索引元組所需的冒號。例如,如果 x 是rank為的5陣列(即,它具有5個軸),則
- x[1,2,...] 等於 x[1,2,:,:,:]
- x[...,3] 等效於 x[:,:,:,:,3]
- x[4,...,5,:] 等效於 x[4,:,:,5,:]
c = np.array( [[[ 0, 1, 2], # a 3D array (two stacked 2D arrays)
[ 10, 12, 13]],
[[100,101,102],
[110,112,113]]])
print('c.shape is ',c.shape,'\n')
print('c[1,...] is :\n',c[1,...],'\n') # same as c[1,:,:] or c[1]
print('c[...,2] is :\n',c[...,2],'\n') # same as c[:,:,2]
c.shape is (2, 2, 3)
c[1,...] is :
[[100 101 102]
[110 112 113]]
c[...,2] is :
[[ 2 13]
[102 113]]
迭代(Iterating) 多維陣列是相對於第一個軸完成的:
for row in c:
print(row,'\n')
[[ 0 1 2]
[10 12 13]]
[[100 101 102]
[110 112 113]]
但是,如果想要對陣列中的每個元素執行操作,可以使用 flat 屬性,該屬性是陣列中所有元素的迭代器:
for element in c.flat:
print(element)
0
1
2
10
12
13
100
101
102
110
112
113