NumPy 官方快速入門教程(譯)

寫在前面:原本是學習下 NumPy,看到官網的入門教程想跟着實驗一下,怕不經常使用,而我這人健忘,因此記錄下來。索性就照着翻譯一下,一樣能夠提高本身的閱讀和寫做能力,須要的能夠存一下。固然,本人水平有限,有錯誤的地方歡迎你們指正。這裏是基於 NumPy\ v1.13.dev0\ Manual 翻譯的。截止時間2018/02/04html

快速入門教程

1 準備工做

在你瀏覽這個指導以前,你應該懂一點 Python 。若是你想回顧一下能夠看Python tutorial。若是你想把教程的代碼跑起來,必須安裝一些軟件,請參考scipy.org/install.htm…python

2 基礎知識

NumPy 的主要操做對象是同類型的多維數組。它是一個由正整數元組索引,元素類型相同的表(一般元素是數字)。在 NumPy 維度被稱爲 axes, axes 的數量稱爲 rank數組

例如,在 3D 空間的一個點 [1, 2, 1] 是一個 rank = 1 的數組,由於它只有一個 axes。這個 axes 的長度是 3。在下面這個例子中,數組 rank = 2 (它是 2維的)。第一維(axes)長度是 2,第二位長度是 3緩存

[[ 1., 0., 0. ],
 [ 0., 1., 2. ]]
複製代碼

NumPy 的數組類是 ndarray。也能夠叫作 array。說到這裏,numpy.array 和標準 Python 庫中的 array.array 是不同的,它只能處理一維的數組和提供更少的功能。ndarray 對象的一些重要屬性以下:bash

ndarray.ndim

數組的 axes (維數)數值大小。在 Python 中維數的大小能夠參考 rankapp

ndarray.shape

數組的維數,這是由每一個維度的大小組成的一個元組。對於一個 nm 列的矩陣。shape(n, m)。由 shape 元組的長度得出 rank 或者維數 ndimdom

ndarray.size

數組元素的個數總和,這等於 shape 元組數字的乘積。ide

ndarray.dtype

在數組中描述元素類型的一個對象。它是一種能夠用標準的 Python 類型建立和指定的類型。另外,NumPy也提供了它本身的類型:numpy.int32numpy.int16numpy.float64……函數

ndarray.itemsize

數組中每一個元素所佔字節數。例如,一個 float64itemsize8 ( = 64/8bit)complex32itemsize4 ( = 32/8bit)。它和 ndarray.dtype.itemsize 是相等的。佈局

ndarray.data

數組實際元素的緩存區。一般來講,咱們不須要使用這個屬性,由於咱們會使用索引的方式訪問數據。

2.1 例子

>>> import numpy as np
>>> a = np.arange(15).reshape(3, 5)
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int64'
>>> a.itemsize
8
>>> a.size
15
>>> type(a)
<type 'numpy.ndarray'>
>>> b = np.array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
<type 'numpy.ndarray'>
複製代碼

2.2 建立數組

這裏有幾種方法建立數組。

例如,你可使用 array 函數從一個常規的 Python 列表或元組建立一個數組。建立的數組類型是從原始序列中的元素推斷出來的。

>>> import numpy as np
>>> a = np.array([2,3,4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int64')
>>> b = np.array([1.2, 3.5, 5.1])
>>> b.dtype
dtype('float64')
複製代碼

一個常見錯誤是在調用 array 函數時,傳遞的參數是多個數值而不是一個單獨的數字列表。

>>> a = np.array(1,2,3,4)    # WRONG
>>> a = np.array([1,2,3,4])  # RIGHT
複製代碼

array 將序列轉化成高維數組

>>> b = np.array([(1.5,2,3), (4,5,6)])
>>> b
array([[ 1.5,  2. ,  3. ],
       [ 4. ,  5. ,  6. ]])
複製代碼

數組的類型也可以在建立時具體指定:

>>> c = np.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 建立一個隨機的數組。默認建立數組的類型是 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 )                # dtype can also be specified
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) )                                 # uninitialized, output may vary
array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],
       [  5.30498948e-313,   3.14673309e-307,   1.00000000e+000]])
複製代碼

爲了建立數字序列,NumPy 提供了一個和 range 類似的函數,能夠返回一個數組而不是列表。

>>> np.arange( 10, 30, 5 )
array([10, 15, 20, 25])
>>> np.arange( 0, 2, 0.3 )                 # it accepts float arguments
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 )                 # 9 numbers from 0 to 2
array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ,  1.25,  1.5 ,  1.75,  2.  ])
>>> x = np.linspace( 0, 2*pi, 100 )        # useful to evaluate function at lots of points
>>> f = np.sin(x)
複製代碼
參考

array, zeros, zeros_like, ones, ones_like, empty, empty_like, arange, linspace, numpy.random.rand, numpy.random.randn, fromfunction, fromfile

2.3 打印數組

當你打印數組時,NumPy 顯示出來和嵌套的列表類似,可是具備如下佈局:

  • 最後一個 axis 從左到右打印,
  • 第二到最後一個從上到下打印,
  • 剩餘的也是從上到下打印,每一片經過一個空行隔開。
>>> a = np.arange(6)                         # 1d array
>>> print(a)
[0 1 2 3 4 5]
>>>
>>> b = np.arange(12).reshape(4,3)           # 2d array
>>> print(b)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
>>>
>>> c = np.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(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]]
複製代碼

爲了取消這種行爲,強制 NumPy 去打印整個數組,你能夠經過 set_printoptions 改變打印選項。

>>> np.set_printoptions(threshold='nan')
複製代碼

2.4 基本操做

在數組上的算數運算應用於每一個元素。並建立一個用結果填充的新的數組。

>>> a = np.array( [20,30,40,50] )
>>> b = np.arange( 4 )
>>> b
array([0, 1, 2, 3])
>>> c = a-b
>>> c
array([20, 29, 38, 47])
>>> b**2
array([0, 1, 4, 9])
>>> 10*np.sin(a)
array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854])
>>> a<35
array([ True, True, False, False], dtype=bool)
複製代碼

NumPy 數組的 * 操做不像其餘的矩陣語言。矩陣乘法經過 dot 函數進行模擬。

>>> A = np.array( [[1,1],
...             [0,1]] )
>>> B = np.array( [[2,0],
...             [3,4]] )
>>> A*B                         # elementwise product
array([[2, 0],
       [0, 4]])
>>> A.dot(B)                    # matrix product
array([[5, 4],
       [3, 4]])
>>> np.dot(A, B)                # another matrix product
array([[5, 4],
       [3, 4]])
複製代碼

+=*= 操做之類的,直接在原數組上作修改,不會建立新數組。

>>> a = np.ones((2,3), dtype=int)
>>> b = np.random.random((2,3))
>>> a *= 3
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
>>> b += a
>>> b
array([[ 3.417022  ,  3.72032449,  3.00011437],
       [ 3.30233257,  3.14675589,  3.09233859]])
>>> a += b                  # b is not automatically converted to integer type
Traceback (most recent call last):
  ...
TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
複製代碼

在不一樣數組類型之間的操做,結果數組的類型趨於更普通或者更精確的一種(稱爲向上轉型)

>>> a = np.ones(3, dtype=np.int32)
>>> b = np.linspace(0,pi,3)
>>> b.dtype.name
'float64'
>>> c = a+b
>>> c
array([ 1.        ,  2.57079633,  4.14159265])
>>> c.dtype.name
'float64'
>>> d = np.exp(c*1j)
>>> d
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
       -0.54030231-0.84147098j])
>>> d.dtype.name
'complex128'
複製代碼

許多相似於求數組全部元素的和的一元操做都是做爲 ndarray 類的方法實現的。

>>> a = np.random.random((2,3))
>>> a
array([[ 0.18626021,  0.34556073,  0.39676747],
       [ 0.53881673,  0.41919451,  0.6852195 ]])
>>> a.sum()
2.5718191614547998
>>> a.min()
0.1862602113776709
>>> a.max()
0.6852195003967595
複製代碼

默認狀況下,儘管這些操做是應用於一個數字列表,能夠無視它的形狀。當時,經過指定 axis 參數能夠將操做應用於數組的某一具體 axis

>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> b.sum(axis=0)                            # sum of each column
array([12, 15, 18, 21])
>>>
>>> b.min(axis=1)                            # min of each row
array([0, 4, 8])
>>>
>>> b.cumsum(axis=1)                         # cumulative sum along each row
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38]])
複製代碼

2.5 通用功能

NumPy 提供了不少數學上的函數,例如 sincosexp。這些被叫作 "universal functions" (ufunc)。在 $ NumPy \)中這些函數是操做數組數字,產生一個數組做爲輸出。

>>> B = np.arange(3)
>>> B
array([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.])
複製代碼
參考

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

2.6 索引,切片和迭代

一維數組能夠被索引,切片和迭代,就像列表和其餘Python序列同樣。

>>> a = np.arange(10)**3
>>> a
array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729])
>>> a[2]
8
>>> a[2:5]
array([ 8, 27, 64])
>>> a[:6:2] = -1000    # equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
>>> a
array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,   729])
>>> a[ : :-1]                                 # reversed a
array([  729,   512,   343,   216,   125, -1000,    27, -1000,     1, -1000])
>>> for i in a:
...     print(i**(1/3.))
...
nan
1.0
nan
3.0
nan
5.0
6.0
7.0
8.0
9.0
複製代碼

多維數組對於每一個 axis 都有一個索引,這些索引用逗號分隔。

>>> def f(x,y):
...     return 10*x+y
...
>>> b = np.fromfunction(f,(5,4),dtype=int)
>>> b
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])
>>> b[2,3]
23
>>> b[0:5, 1]                       # each row in the second column of b
array([ 1, 11, 21, 31, 41])
>>> b[ : ,1]                        # equivalent to the previous example
array([ 1, 11, 21, 31, 41])
>>> b[1:3, : ]                      # each column in the second and third row of b
array([[10, 11, 12, 13],
       [20, 21, 22, 23]])
複製代碼

當提供的索引少於 axis 的數量時,缺失的索引按徹底切片考慮。

>>> b[-1]                                  # the last row. Equivalent to b[-1,:]
array([40, 41, 42, 43])
複製代碼

b[i] 這種表達中括號中的 i 後面能夠跟不少用 : 表示其它 axis 的實例。NumPy 也容許使用三個點代替 b[i, ...]

這三個點(...)表示不少完整索引元組中的冒號。例如,xrank = 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]]])
>>> c.shape
(2, 2, 3)
>>> c[1,...]                                   # same as c[1,:,:] or c[1]
array([[100, 101, 102],
       [110, 112, 113]])
>>> c[...,2]                                   # same as c[:,:,2]
array([[  2,  13],
       [102, 113]])
複製代碼

迭代多維數組是對第一 axis 進行的。

>>> 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 屬性,它是一個 iterator,可以遍歷數組中每個元素。

>>> for element in b.flat:
...     print(element)
...
0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33
40
41
42
43
複製代碼
參考

Indexing, Indexing (reference), newaxis, ndenumerate, indices

3 操控形狀

3.1 改變數組的形狀

每個數組的形狀經過每個 axis 中的元素數量。(其實就是每個維度的元素多少肯定)

>>> a = np.floor(10*np.random.random((3,4)))
>>> a
array([[ 2.,  8.,  0.,  6.],
       [ 4.,  5.,  1.,  1.],
       [ 8.,  9.,  3.,  6.]])
>>> a.shape
(3, 4)
複製代碼

數組的形狀能夠經過不少命令來改變,提到這裏,接下來的三個例子放回一個被修改的數組,原數組不會改變。

>>> a.ravel()  # returns the array, flattened
array([ 2.,  8.,  0.,  6.,  4.,  5.,  1.,  1.,  8.,  9.,  3.,  6.])
>>> a.reshape(6,2)  # returns the array with a modified shape
array([[ 2.,  8.],
       [ 0.,  6.],
       [ 4.,  5.],
       [ 1.,  1.],
       [ 8.,  9.],
       [ 3.,  6.]])
>>> a.T  # returns the array, transposed
array([[ 2.,  4.,  8.],
       [ 8.,  5.,  9.],
       [ 0.,  1.,  3.],
       [ 6.,  1.,  6.]])
>>> a.T.shape
(4, 3)
>>> a.shape
(3, 4)
複製代碼

ravel() 函數中每一個元素的位置一般是一種 「C-style」 的,也就是說,最右邊的索引改變起來最快。因此元素 a[0, 0] 後面的元素是 a[0, 1]。若是這個數組被塑形成其它形狀,這個數組也是做爲 「C-style」 對待。NumPy 一般也是按照這個建立的數組,因此使用 ravel() 函數時不須要複製,可是若是這個數組是經過從另外一個數組切片或者其它不一樣尋常的方式而來的話,它就須要進行復制了。函數 ravel()reshape() 也能夠經過可選參數被指定去用 FORTRAN-style 的數組,這這種風格中,最左的索引改變最快。

reshape 函數返回修改的形狀,而 ndarray.resize 方法直接修改數組自己。

>>> a
array([[ 2.,  8.,  0.,  6.],
       [ 4.,  5.,  1.,  1.],
       [ 8.,  9.,  3.,  6.]])
>>> a.resize((2,6))
>>> a
array([[ 2.,  8.,  0.,  6.,  4.,  5.],
       [ 1.,  1.,  8.,  9.,  3.,  6.]])
複製代碼

若是一個維度給一個 -1 做爲參數,那麼其餘它維度將自動計算。

>>> a.reshape(3,-1)
array([[ 2.,  8.,  0.,  6.],
       [ 4.,  5.,  1.,  1.],
       [ 8.,  9.,  3.,  6.]])
複製代碼
參考

ndarray.shape, reshape, resize, ravel

3.2 不一樣數組的組合

數組能夠經過不一樣的 axes 組合起來。

>>> a = np.floor(10*np.random.random((2,2)))
>>> a
array([[ 8.,  8.],
       [ 0.,  0.]])
>>> b = np.floor(10*np.random.random((2,2)))
>>> b
array([[ 1.,  8.],
       [ 0.,  4.]])
>>> np.vstack((a,b))
array([[ 8.,  8.],
       [ 0.,  0.],
       [ 1.,  8.],
       [ 0.,  4.]])
>>> np.hstack((a,b))
array([[ 8.,  8.,  1.,  8.],
       [ 0.,  0.,  0.,  4.]])
複製代碼

column_stack 函數能夠將 1D 數組做爲 2D 數組的列。當且僅當數組是 1D 的時候它等於 vstack

>>> from numpy import newaxis
>>> np.column_stack((a,b))   # With 2D arrays
array([[ 8.,  8.,  1.,  8.],
       [ 0.,  0.,  0.,  4.]])
>>> a = np.array([4.,2.])
>>> b = np.array([2.,8.])
>>> a[:,newaxis]  # This allows to have a 2D columns vector
array([[ 4.],
       [ 2.]])
>>> np.column_stack((a[:,newaxis],b[:,newaxis]))
array([[ 4.,  2.],
       [ 2.,  8.]])
>>> np.vstack((a[:,newaxis],b[:,newaxis])) # The behavior of vstack is different
array([[ 4.],
       [ 2.],
       [ 2.],
       [ 8.]])
複製代碼

對於超過兩個維度的數組,hstack 會沿着第二個 axis 堆積,vstack 沿着第一個 axes 堆積,concatenate 容許一個可選參數選擇哪個 axis 發生鏈接操做。

提示

在複雜狀況下,r_c_ 對於經過沿一個 axis 堆積數字來建立數組頗有用。它們容許使用範圍表示符號(「:」)

>>> np.r_[1:4,0,4]
array([1, 2, 3, 0, 4])
複製代碼

當使用數組做爲參數時,r_c_ 在默認行爲是和 vstackhstack 類似的,可是它們容許可選參數給出 axis 來鏈接。

參考

hstackvstackcolumn_stackconcatenatec_r_

3.3 將數組分割成幾個小數組

使用 hsplit,你能沿着它的水平 axis 分割,能夠經過指定數組形狀來返回,也能夠指定哪一個列應該拆分:

>>> a = np.floor(10*np.random.random((2,12)))
>>> a
array([[ 9.,  5.,  6.,  3.,  6.,  8.,  0.,  7.,  9.,  7.,  2.,  7.],
       [ 1.,  4.,  9.,  2.,  2.,  1.,  0.,  6.,  2.,  2.,  4.,  0.]])
>>> np.hsplit(a,3)   # Split a into 3
[array([[ 9.,  5.,  6.,  3.],
       [ 1.,  4.,  9.,  2.]]), array([[ 6.,  8.,  0.,  7.],
       [ 2.,  1.,  0.,  6.]]), array([[ 9.,  7.,  2.,  7.],
       [ 2.,  2.,  4.,  0.]])]
>>> np.hsplit(a,(3,4))   # Split a after the third and the fourth column
[array([[ 9.,  5.,  6.],
       [ 1.,  4.,  9.]]), array([[ 3.],
       [ 2.]]), array([[ 6.,  8.,  0.,  7.,  9.,  7.,  2.,  7.],
       [ 2.,  1.,  0.,  6.,  2.,  2.,  4.,  0.]])]
複製代碼

vplit 沿着豎直的 axis 分割,array_split 容許經過指定哪一個 axis 去分割。

4 拷貝和 Views

在操做數組的時候,它們的數據有時候拷貝進一個新的數組,有時候又不是。這常常是初學者感到困惑。下面有三種狀況:

4.1 不拷貝

簡單的賦值不會拷貝任何數組對象和它們的數據。

>>> a = np.arange(12)
>>> b = a            # no new object is created
>>> b is a           # a and b are two names for the same ndarray object
True
>>> b.shape = 3,4    # changes the shape of a
>>> a.shape
(3, 4)
複製代碼

Python 將可變對象做爲引用傳遞,因此函數調用不會產生拷貝。

>>> def f(x):
...     print(id(x))
...
>>> id(a)                           # id is a unique identifier of an object
148293216
>>> f(a)
148293216
複製代碼

4.2 View 或者淺拷貝

不一樣的數組對象能夠分享相同的數據。view 方法建立了一個相同數據的新數組對象。 PS:這裏 View(視圖?) 不知道如何理解好,因此保留。

>>> c = a.view()
>>> c is a
False
>>> c.base is a                        # c is a view of the data owned by a
True
>>> c.flags.owndata
False
>>>
>>> c.shape = 2,6                      # a's shape doesn't change
>>> a.shape
(3, 4)
>>> c[0,4] = 1234                      # a's data changes
>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])
複製代碼

切片數組返回一個 view

>>> s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:,1:3]"
>>> s[:] = 10           # s[:] is a view of s. Note the difference between s=10 and s[:]=10
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])
複製代碼

4.3 深拷貝

copy 方法徹底拷貝數組。

>>> d = a.copy()                          # a new array object with new data is created
>>> d is a
False
>>> d.base is a                           # d doesn't share anything with a
False
>>> d[0,0] = 9999
>>> a
array([[   0,   10,   10,    3],
       [1234,   10,   10,    7],
       [   8,   10,   10,   11]])
複製代碼

4.4 函數和方法綜述

這裏經過類別排序列舉一些有用的 NumPy 函數和方法。拆看完整列表點擊Routines

數組收集

arange, array, copy, empty, empty_like, eye, fromfile, fromfunction, identity, linspace, logspace, mgrid, ogrid, ones, ones_like, r, zeros, zeros_like

轉化

ndarray.astype, atleast_1d, atleast_2d, atleast_3d, mat

操做

array_split, column_stack, concatenate, diagonal, dsplit, dstack, hsplit, hstack, ndarray.item, newaxis, ravel, repeat, reshape, resize, squeeze, swapaxes, take, transpose, vsplit, vstack

疑問

all, any, nonzero, where

排序

argmax, argmin, argsort, max, min, ptp, searchsorted, sort

運算

choose, compress, cumprod, cumsum, inner, ndarray.fill, imag, prod, put, putmask, real, sum

基本統計

cov, mean, std, var

基本線性代數

cross, dot, outer, linalg.svd, vdot

5 Less Basic

5.1 廣播規則

廣播容許通用功能用一種有意義的方式去處理不徹底相同的形狀輸入。 第一條廣播規則是若是全部輸入的數組都沒有相同的維度數字,那麼將會重複地用 1 去加在較小的數組形狀上直到全部的數組有相同的維度數字。 第二條廣播規則是確保沿着特定維度大小爲 1 的數組就像沿着這個維度最大維數大小同樣的,假設數組元素的值在廣播數組的維度是相同的。 應用廣播規則後,全部數組大小沒必要須匹配。更多細節能夠在Broadcasting

6 花式索引和索引技巧

NumPy 提供了比 Python 序列更多的索引功能。除了咱們以前看到的經過整數和切片索引以外,數組能夠經過整數數組和布爾數組索引。

6.1 用索引數組索引

>>> a = np.arange(12)**2                       # the first 12 square numbers
>>> i = np.array( [ 1,1,3,8,5 ] )              # an array of indices
>>> a[i]                                       # the elements of a at the positions i
array([ 1,  1,  9, 64, 25])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] )      # a bidimensional array of indices
>>> a[j]                                       # the same shape as j
array([[ 9, 16],
       [81, 49]])
複製代碼

當數組 a 是多維的,單個數組指向數組 a 的第一維。如下示例經過使用調色板將標籤圖像轉換爲彩色圖像來顯示此行爲。

>>> palette = np.array( [ [0,0,0],                # black
...                       [255,0,0],              # red
...                       [0,255,0],              # green
...                       [0,0,255],              # blue
...                       [255,255,255] ] )       # white
>>> image = np.array( [ [ 0, 1, 2, 0 ],           # each value corresponds to a color in the palette
...                     [ 0, 3, 4, 0 ]  ] )
>>> palette[image]                            # the (2,4,3) color image
array([[[  0,   0,   0],
        [255,   0,   0],
        [  0, 255,   0],
        [  0,   0,   0]],
       [[  0,   0,   0],
        [  0,   0, 255],
        [255, 255, 255],
        [  0,   0,   0]]])
複製代碼

咱們能夠給超過一維的索引。數組每一個維度的索引形狀必須同樣。

>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> i = np.array( [ [0,1],                        # indices for the first dim of a
...                 [1,2] ] )
>>> j = np.array( [ [2,1],                        # indices for the second dim
...                 [3,3] ] )
>>>
>>> a[i,j]                                     # i and j must have equal shape
array([[ 2,  5],
       [ 7, 11]])
>>>
>>> a[i,2]
array([[ 2,  6],
       [ 6, 10]])
>>>
>>> a[:,j]                                     # i.e., a[ : , j]
array([[[ 2,  1],
        [ 3,  3]],
       [[ 6,  5],
        [ 7,  7]],
       [[10,  9],
        [11, 11]]])
複製代碼

固然,咱們能夠把 i, j 放進一個序列而後對這個列表進行索引。

>>> l = [i,j]
>>> a[l]                                       # equivalent to a[i,j]
array([[ 2,  5],
       [ 7, 11]])
複製代碼

然而,咱們能夠直接把 ij 放進數組中,由於這個數組將會被解釋成 a 第一維的索引。

>>> s = np.array( [i,j] )
>>> a[s]                                       # not what we want
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IndexError: index (3) out of range (0<=index<=2) in dimension 0
>>>
>>> a[tuple(s)]                                # same as a[i,j]
array([[ 2,  5],
       [ 7, 11]])
複製代碼

另外一個經常使用數組索引是查詢時間相關係列的最大值。

>>> time = np.linspace(20, 145, 5)                 # time scale
>>> data = np.sin(np.arange(20)).reshape(5,4)      # 4 time-dependent series
>>> time
array([  20.  ,   51.25,   82.5 ,  113.75,  145.  ])
>>> data
array([[ 0.        ,  0.84147098,  0.90929743,  0.14112001],
       [-0.7568025 , -0.95892427, -0.2794155 ,  0.6569866 ],
       [ 0.98935825,  0.41211849, -0.54402111, -0.99999021],
       [-0.53657292,  0.42016704,  0.99060736,  0.65028784],
       [-0.28790332, -0.96139749, -0.75098725,  0.14987721]])
>>>
>>> ind = data.argmax(axis=0)                   # index of the maxima for each series
>>> ind
array([2, 0, 3, 1])
>>>
>>> time_max = time[ ind]                       # times corresponding to the maxima
>>>
>>> data_max = data[ind, xrange(data.shape[1])] # => data[ind[0],0], data[ind[1],1]...
>>>
>>> time_max
array([  82.5 ,   20.  ,  113.75,   51.25])
>>> data_max
array([ 0.98935825,  0.84147098,  0.99060736,  0.6569866 ])
>>>
>>> np.all(data_max == data.max(axis=0))
True
複製代碼

你也可使用數組索引對數組進行賦值:

>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> a[[1,3,4]] = 0
>>> a
array([0, 0, 2, 0, 0])
複製代碼

然而,當你的列表索引包含重複,這個賦值會發生幾回,保留最後一個數值。

>>> a = np.arange(5)
>>> a[[0,0,2]]=[1,2,3]
>>> a
array([2, 1, 3, 3, 4])
複製代碼

這足夠合理,可是若是你想使用 Python+= 結構時要當心,它可能不像你期待的同樣:

>>> a = np.arange(5)
>>> a[[0,0,2]]+=1
>>> a
array([1, 1, 3, 3, 4])
複製代碼

即便 0 在列表中出現了兩次,這第 0 個元素也只增長一次。這是由於 Python 把 「a+=1」 等價於 「a=a+1」。

6.2 用布爾數組索引

當咱們用整數數組去索引數組時,咱們提供了索引列表去挑選。用布爾索引的方法是不用的;咱們明確的在數組中選擇哪一個咱們想要哪一個咱們不想要。 最天然能想到的方法是用和原數組同樣形狀的布爾數組進行布爾索引。

>>> a = np.arange(12).reshape(3,4)
>>> b = a > 4
>>> b                                          # b is a boolean with a's shape
array([[False, False, False, False],
       [False,  True,  True,  True],
       [ True,  True,  True,  True]], dtype=bool)
>>> a[b]                                       # 1d array with the selected elements
array([ 5,  6,  7,  8,  9, 10, 11])
複製代碼

這個屬性在複製時很是有用。

>>> a[b] = 0                                   # All elements of 'a' higher than 4 become 0
>>> a
array([[0, 1, 2, 3],
       [4, 0, 0, 0],
       [0, 0, 0, 0]])
複製代碼

你能夠看接下來的例子去了解如何使用布爾索引去生成 Mandelbrot set 圖像。

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> def mandelbrot( h,w, maxit=20 ):
...     """Returns an image of the Mandelbrot fractal of size (h,w)."""
...     y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]
...     c = x+y*1j
...     z = c
...     divtime = maxit + np.zeros(z.shape, dtype=int)
...
...     for i in range(maxit):
...         z = z**2 + c
...         diverge = z*np.conj(z) > 2**2            # who is diverging
...         div_now = diverge & (divtime==maxit)  # who is diverging now
...         divtime[div_now] = i                  # note when
...         z[diverge] = 2                        # avoid diverging too much
...
...     return divtime
>>> plt.imshow(mandelbrot(400,400))
>>> plt.show()
複製代碼
import numpy as np
import matplotlib.pyplot as plt

def mandelbrot(h, w, maxit=20):
    y, x = np.ogrid[-1.4:1.4:h * 1j, -2:0.8:w * 1j]
    c = x + y * 1j
    z = c
    divtime = maxit + np.zeros(z.shape, dtype=int)
    for i in range(maxit):
        z = z ** 2 + c
        diverge = z * np.conj(z) > 2 ** 2  # who is diverging
        div_now = diverge & (divtime == maxit)  # who is diverging now
        divtime[div_now] = i  # note when
        z[diverge] = 2  # avoid diverging too much
    return divtime

plt.imshow(mandelbrot(400, 400))
plt.show()
複製代碼

第二種用布爾索引方法更像是整數索引,對於每一個數組的維度,咱們給一個 1D 的布爾數組去選擇咱們想要的切片。

>>> a = np.arange(12).reshape(3,4)
>>> b1 = np.array([False,True,True])             # first dim selection
>>> b2 = np.array([True,False,True,False])       # second dim selection
>>>
>>> a[b1,:]                                   # selecting rows
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> a[b1]                                     # same thing
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> a[:,b2]                                   # selecting columns
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
>>>
>>> a[b1,b2]                                  # a weird thing to do
array([ 4, 10])
複製代碼

請注意,1D 布爾數組的長度必須與你要切片的維度(或axis)的長度一致。在以前的例子中,b1 是一個長度爲 3a 的行數) 的 1-rank 數組,b2 (長度爲 $ 4 $)是一個適合去索引 a 的第二 rank (列)。

6.3 ix_() 函數

ix_ 能夠組合不一樣向量去得到對於每個 n-uplet 的結果。例如,若是你想從每一個 a, b, c 向量中取得三元組去計算全部的 a+b*c

>>> a = np.array([2,3,4,5])
>>> b = np.array([8,5,4])
>>> c = np.array([5,4,6,8,3])
>>> ax,bx,cx = np.ix_(a,b,c)
>>> ax
array([[[2]],
       [[3]],
       [[4]],
       [[5]]])
>>> bx
array([[[8],
        [5],
        [4]]])
>>> cx
array([[[5, 4, 6, 8, 3]]])
>>> ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
>>> result = ax+bx*cx
>>> result
array([[[42, 34, 50, 66, 26],
        [27, 22, 32, 42, 17],
        [22, 18, 26, 34, 14]],
       [[43, 35, 51, 67, 27],
        [28, 23, 33, 43, 18],
        [23, 19, 27, 35, 15]],
       [[44, 36, 52, 68, 28],
        [29, 24, 34, 44, 19],
        [24, 20, 28, 36, 16]],
       [[45, 37, 53, 69, 29],
        [30, 25, 35, 45, 20],
        [25, 21, 29, 37, 17]]])
>>> result[3,2,4]
17
>>> a[3]+b[2]*c[4]
17
複製代碼

你也能夠按如下方式實現:

>>> def ufunc_reduce(ufct, *vectors):
...    vs = np.ix_(*vectors)
...    r = ufct.identity
...    for v in vs:
...        r = ufct(r,v)
...    return r
複製代碼

而後這樣使用:

>>> ufunc_reduce(np.add,a,b,c)
array([[[15, 14, 16, 18, 13],
        [12, 11, 13, 15, 10],
        [11, 10, 12, 14,  9]],
       [[16, 15, 17, 19, 14],
        [13, 12, 14, 16, 11],
        [12, 11, 13, 15, 10]],
       [[17, 16, 18, 20, 15],
        [14, 13, 15, 17, 12],
        [13, 12, 14, 16, 11]],
       [[18, 17, 19, 21, 16],
        [15, 14, 16, 18, 13],
        [14, 13, 15, 17, 12]]])
複製代碼

這個版本的比一般的 ufunc.reduce 好在它使用了Broadcasting Rules 規則去避免建立一個大小是輸出乘以矢量數量數組。

6.4 使用字符串索引

參考Structured arrays

7 線性代數

工做進行中,基本的線性代數包含在其中。

7.1 簡單的數組操做

NumPy 文件夾下的 linalg.py 文件瞭解更多。

>>> import numpy as np
>>> a = np.array([[1.0, 2.0], [3.0, 4.0]])
>>> print(a)
[[ 1.  2.]
 [ 3.  4.]]

>>> a.transpose()
array([[ 1.,  3.],
       [ 2.,  4.]])

>>> np.linalg.inv(a)
array([[-2. ,  1. ],
       [ 1.5, -0.5]])

>>> u = np.eye(2) # unit 2x2 matrix; "eye" represents "I"
>>> u
array([[ 1.,  0.],
       [ 0.,  1.]])
>>> j = np.array([[0.0, -1.0], [1.0, 0.0]])

>>> np.dot (j, j) # matrix product
array([[-1.,  0.],
       [ 0., -1.]])

>>> np.trace(u)  # trace
2.0

>>> y = np.array([[5.], [7.]])
>>> np.linalg.solve(a, y)
array([[-3.],
       [ 4.]])

>>> np.linalg.eig(j)
(array([ 0.+1.j,  0.-1.j]), array([[ 0.70710678+0.j        ,  0.70710678-0.j        ],
       [ 0.00000000-0.70710678j,  0.00000000+0.70710678j]]))
複製代碼
Parameters:
    square matrix
Returns
    The eigenvalues, each repeated according to its multiplicity.
    The normalized (unit "length") eigenvectors, such that the
    column ``v[:,i]`` is the eigenvector corresponding to the
    eigenvalue ``w[i]`` .
複製代碼

8 技巧和提示

這裏咱們給出一些有用的小技巧。

8.1 「自動塑形」

爲了改變數組的維度,你能夠省略一個能夠自動被推算出來的大小的參數。

>>> a = np.arange(30)
>>> a.shape = 2,-1,3  # -1 means "whatever is needed"
>>> a.shape
(2, 5, 3)
>>> a
array([[[ 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]]])
複製代碼

8.2 矢量疊加

咱們怎麼從一個相同大小的行向量構造出一個 2D 數組?在 MATLAB中是至關簡單的:若是 xy 是兩個相同長度的向量,你只須要把 m=[x;y]。在 NumPy 中,經過函數 column_stackdstackhstackvstack 實現,這取決於所要疊加的維度。例如:

x = np.arange(0,10,2)                     # x=([0,2,4,6,8])
y = np.arange(5)                          # y=([0,1,2,3,4])
m = np.vstack([x,y])                      # m=([[0,2,4,6,8],
                                          # [0,1,2,3,4]])
xy = np.hstack([x,y])                     # xy =([0,2,4,6,8,0,1,2,3,4])
複製代碼

在超過兩個維度時這些函數背後的邏輯是奇怪的。

參考

NumPy for Matlab users

8.3 柱狀圖

NumPyhistogram 函數應用於數組,返回一對矢量:數組的柱狀圖和 bins 矢量。小心:matplotlib 也有一個函數去構建柱狀圖(叫作 hist,一樣在 Matlab 中),這個和 NumPy 仍是不同的。主要的區別是 pylab.hist 自動繪製柱狀圖而 matplotlib 只是生成數據。

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> # Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
>>> mu, sigma = 2, 0.5
>>> v = np.random.normal(mu,sigma,10000)
>>> # Plot a normalized histogram with 50 bins
>>> plt.hist(v, bins=50, normed=1)       # matplotlib version (plot)
>>> plt.show()
複製代碼
import numpy as np
import matplotlib.pyplot as plt

# Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
mu, sigma = 2, 0.5
v = np.random.normal(mu, sigma, 10000)
# Plot a normalized histogram with 50 bins
plt.hist(v, bins=50, normed=1)  # matplotlib version (plot)
plt.show()
複製代碼

>>> # Compute the histogram with numpy and then plot it
>>> (n, bins) = np.histogram(v, bins=50, normed=True)  # NumPy version (no plot)
>>> plt.plot(.5*(bins[1:]+bins[:-1]), n)
>>> plt.show()
複製代碼
import numpy as np
import matplotlib.pyplot as plt

# Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
mu, sigma = 2, 0.5
v = np.random.normal(mu, sigma, 10000)
# Compute the histogram with numpy and then plot it
(n, bins) = np.histogram(v, bins=50, normed=True)  # NumPy version (no plot)
plt.plot(.5 * (bins[1:] + bins[:-1]), n)
plt.show()
複製代碼

9 更多閱讀

相關文章
相關標籤/搜索