1. 程式人生 > >numpy快速入門(一)

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