NumPy快速入門指南

參考:
https://docs.scipy.org/doc/numpy-dev/user/quickstart.html

準(zhǔn)備

安裝numpy

$ pip install numpy

基礎(chǔ)

In NumPy dimensions are called axes. The number of axes is rank.

Numpy中,維度被稱作axes, 維度數(shù)被稱作rank

Numpy的數(shù)組類是ndarray, 與標(biāo)準(zhǔn)python庫(kù)的數(shù)組不太一樣,它包含的元素必須是相同類型的。

ndarray的常見屬性如下:

  • ndarray.ndim數(shù)組的軸數(shù)(即rank)
  • ndarray.shape數(shù)組的維度,返回的是一個(gè)元組,元組的長(zhǎng)度值剛好是ndim
  • ndarray.size數(shù)組元素的個(gè)數(shù)
  • ndarray.dtype數(shù)組元素的類型
  • ndarray.itemsize數(shù)組元素的字節(jié)大小
  • ndarray.data數(shù)組包含的實(shí)際數(shù)據(jù)(一般情況下不會(huì)用到這個(gè)屬性,都是通過索引來訪問元素)

數(shù)組例子

>>> 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]])

>>> type(a)
numpy.ndarray

>>> a.ndim
2

>>> a.shape
(3, 5)

>>> a.size
15

>>> a.dtype
dtype('int64')

>>> a.itemsize
8

>>> a.data
<memory at 0x11221b120>

創(chuàng)建數(shù)組

創(chuàng)建數(shù)組一般有如下幾種方法:

通過array函數(shù),可以從普通的python列表或元組來創(chuàng)建

>>> 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')

一個(gè)常見的錯(cuò)誤就是在調(diào)用array函數(shù)時(shí), 傳遞多個(gè)參數(shù),而不是一個(gè)列表

>>> a = np.array(1,2,3,4)    # 錯(cuò)誤
>>> a = np.array([1,2,3,4])  # 正確

array同樣可以接受列表序列并將它轉(zhuǎn)換為多維數(shù)組

>>> c = np.array([(1.5, 2.3), (4,5,6)])

>>> c
array([(1.5, 2.3), (4, 5, 6)], dtype=object)

同樣可以在創(chuàng)建數(shù)組的時(shí)候,指定數(shù)據(jù)類型

>>> d = np.array([[1,2], [3,4]], dtype=complex)

>>> d
array([[ 1.+0.j,  2.+0.j],
       [ 3.+0.j,  4.+0.j]])

通常情況下, 數(shù)組元素的初始數(shù)據(jù)是不知道的,但是知道數(shù)組的大小。因此Numpy提供了一些函數(shù)來創(chuàng)建指定大小的數(shù)組,并用占位符來填充數(shù)組。

  • zeros函數(shù)創(chuàng)建初始值為0的數(shù)組
  • ones創(chuàng)建初始值為1的數(shù)組
  • empty創(chuàng)建未初始化的隨機(jī)數(shù)組

默認(rèn)情況下,上面三個(gè)函數(shù)創(chuàng)建數(shù)組的元素類型都是float64

>>> np.zeros((3,4))
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])
       
>>> np.ones((3,4))
array([[ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.]])
       
>>> np.empty((2,5))
array([[  2.68156159e+154,   2.68679227e+154,   2.37663529e-312,
          2.56761491e-312,   8.48798317e-313],
       [  9.33678148e-313,   8.70018275e-313,   2.02566915e-322,
          0.00000000e+000,   6.95335581e-309]])

為了創(chuàng)建序列函數(shù),Numpy也提供了類似range函數(shù)的方法

>>> np.arange(10, 30, 5)
array([10, 15, 20, 25])

>>> np.arange(0, 2, 0.3)
array([ 0. ,  0.3,  0.6,  0.9,  1.2,  1.5,  1.8])

當(dāng)使用arange函數(shù)的生成float類型的序列時(shí),生成的序列有時(shí)候并不會(huì)按照我們預(yù)期的步長(zhǎng)來生成,要實(shí)現(xiàn)這個(gè)效果,最好是用linspace函數(shù)來代替。例如:

>>> from numpy import pi

>>> np.linspace(0, 2, 9)
array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ,  1.25,  1.5 ,  1.75,  2.  ])

>>> x = np.linspace( 0, 2*pi, 100 )

>>> f=np.sin(x)

除此之外,還可以使用下面的函數(shù)來創(chuàng)建數(shù)組

  • array
  • zeros
  • zeros_like # 創(chuàng)建一個(gè)和給定數(shù)組相同shape的全是0的數(shù)組
  • ones
  • ones_like
  • empty
  • empty_like
  • arange
  • linspace
  • numpy.random.rand # 從 [0, 1) 中返回一個(gè)或多個(gè)樣本值。
  • numpy.random.randn # 從標(biāo)準(zhǔn)正態(tài)分布中返回一個(gè)或多個(gè)樣本值。
  • fromfunction
  • fromfile

打印數(shù)組

當(dāng)使用print函數(shù)打印數(shù)組時(shí),numpy會(huì)輸出一個(gè)嵌套的列表形式

# 一維數(shù)組
>>> a = np.arange(6)
>>> print(a)
[0 1 2 3 4 5]
# 二維數(shù)組
>>> b = np.arange(12).reshape(4,3)
>>> print(b)
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
# 三維數(shù)組
>>> c = np.arange(24).reshape(2,3,4)
>>> 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]]]

當(dāng)數(shù)組包含的元素太多時(shí),會(huì)省略中間的元素,只打印角落的元素

>>> 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]]

如果想禁用這個(gè)行為,強(qiáng)制打印所有的元素,可以開啟set_printoptions選項(xiàng)

>>> np.set_printoptions(threshold=np.nan)
>>> print(np.arange(100))
[ 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]

還原成省略效果

>>> np.set_printoptions(threshold=1000)

設(shè)置打印浮點(diǎn)數(shù)的小數(shù)位數(shù):

np.set_printoptions(precision=4) # 設(shè)置打印浮點(diǎn)數(shù)的小數(shù)位數(shù),默認(rèn)是8位

基本操作

數(shù)組的算術(shù)運(yùn)算會(huì)自動(dòng)作用于每個(gè)元素,并返回一個(gè)新的數(shù)組

>>> a = np.array([20,30,40,50])

>>> b = np.arange(4)

>>> 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)

*返回的是每個(gè)元素相乘的結(jié)果,要實(shí)現(xiàn)矩陣乘法,需要使用dot函數(shù)

>>> a = np.array([ [1, 1],
...                [0, 1]])
...

>>> b = np.array([ [2, 0],
...                [3, 4]])
...

>>> a * b       # 對(duì)應(yīng)位置的元素相乘
array([[2, 0],
       [0, 4]])

>>> a.dot(b)   # 矩陣乘法
array([[5, 4],
       [3, 4]])

>>> np.dot(a, b) # 另一種形式的矩陣乘法
array([[5, 4],
       [3, 4]])

一些操作, 如+=*=是直接修改原有的數(shù)組,而不是新建一個(gè)

>>> a = np.ones((2,3), dtype=int)

>>> a
array([[1, 1, 1],
       [1, 1, 1]])

>>> b = np.random.random((2,3))

>>> b
array([[ 0.7216234 ,  0.5813183 ,  0.21175569],
       [ 0.11697569,  0.89835328,  0.06088455]])

>>> a.dtype
dtype('int64')

>>> b.dtype
dtype('float64')

>>> b+=a

>>> b
array([[ 1.7216234 ,  1.5813183 ,  1.21175569],
       [ 1.11697569,  1.89835328,  1.06088455]])

# 報(bào)錯(cuò)的原因是因?yàn)閍數(shù)組原來是保存int64類型,現(xiàn)在沒法保存float64類型
>>> a+=b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-11-0a45668e3cc6> in <module>()
----> 1 a+=b

TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

當(dāng)不同類型的數(shù)組運(yùn)算操作時(shí),總是向精度更高的自動(dòng)轉(zhuǎn)換

>>> a = np.ones(3, dtype=np.int32)

>>> b = np.linspace(0, np.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包含了很多一元運(yùn)算。如求和等

>>> 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.sum()
105

>>> a.min()
0

>>> a.max()
14

默認(rèn)情況下,這些操作都是作用于每一個(gè)元素,而不管它的維度。但是,我們也可以通過axis參數(shù)來限定操作的軸

>>> b = np.arange(12).reshape(3, 4)

>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# 計(jì)算每一列的和
>>> b.sum(axis=0)
array([12, 15, 18, 21])

# 計(jì)算每一行的最小值
>>> 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]])

通用函數(shù)

Numpy提供了很多常見的數(shù)學(xué)上的運(yùn)算,如sin, cos, exp。在Numpy中,我們稱這些為"universal functions"(ufunc

>>> B = np.arange(3)

>>> B
array([0, 1, 2])

>>> np.exp(B)
array([ 1.        ,  2.71828183,  7.3890561 ])

>>> 2.71828183 * 2.71828183
7.389056107308149

>>> np.sqrt(B)
array([ 0.        ,  1.        ,  1.41421356])

>>> C = np.array([2., -1., 4.])

>>> np.add(B, C)
array([ 2.,  0.,  6.])

索引,切片和迭代

一維數(shù)組的索引,切片,迭代跟普通的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]  # 等價(jià)于a[0:6:2]
array([ 0,  8, 64])

>>> a[:6:2] = -1000

>>> a
array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,   729])

>>> a[::-1]  # 反轉(zhuǎn)數(shù)組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

多維數(shù)組可以在每個(gè)軸上索引,多個(gè)索引用,分隔

>>> 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]])

>>> help(np.fromfunction)


>>> b[2,3]
23

>>> b[0:5, 1]
array([ 1, 11, 21, 31, 41])

>>> b[:, 1]
array([ 1, 11, 21, 31, 41])

>>> b[1:3, :]
array([[10, 11, 12, 13],
       [20, 21, 22, 23]])

當(dāng)索引數(shù)少于軸數(shù)時(shí),缺失的索引認(rèn)為是全切片:

>>> b[-1] # 等價(jià)于 b[-1,:]
array([40, 41, 42, 43])

同樣可以使用...來表示全切片,它代表補(bǔ)全剩下的所有索引。例如數(shù)組x, rank是5.那么

  • x[1,2,...]等價(jià)于x[1,2,:,:,:]

  • x[...,3]等價(jià)于x[:,:,:,:,3]

  • x[4,...,5,:]等價(jià)于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]])
    

多維數(shù)組的迭代是根據(jù)第一個(gè)軸來操作的

>>> b
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])

>>> 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]

如果想遍歷每個(gè)元素,可以使用flat屬性

>>> 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

shape操作

改變數(shù)組的shape

許多函數(shù)都可以改變數(shù)組的shape,但是它們都是返回一個(gè)新的修改后的數(shù)組,并不會(huì)改變?cè)瓟?shù)組

>>> a = np.floor(10*np.random.random((3,4)))

>>> a.shape
(3, 4)

>>> a
array([[ 7.,  8.,  0.,  9.],
       [ 8.,  4.,  9.,  8.],
       [ 4.,  3.,  7.,  0.]])

# 返回降維的數(shù)組
>>> a.ravel()
array([ 7.,  8.,  0.,  9.,  8.,  4.,  9.,  8.,  4.,  3.,  7.,  0.])

# 直接修改shape
>>> a.reshape(6,2)
array([[ 7.,  8.],
       [ 0.,  9.],
       [ 8.,  4.],
       [ 9.,  8.],
       [ 4.,  3.],
       [ 7.,  0.]])

# 數(shù)組轉(zhuǎn)置
>>> a.T
array([[ 7.,  8.,  4.],
       [ 8.,  4.,  3.],
       [ 0.,  9.,  7.],
       [ 9.,  8.,  0.]])

>>> a.T.shape
(4, 3)

>>> a.shape
(3, 4)

reshape返回修改后的數(shù)組,不改變數(shù)組本身,但是resize函數(shù)直接修改原數(shù)組

>>> a
array([[ 7.,  8.,  0.,  9.],
       [ 8.,  4.,  9.,  8.],
       [ 4.,  3.,  7.,  0.]])

>>> a.resize((2,6))

>>> a
array([[ 7.,  8.,  0.,  9.,  8.,  4.],
       [ 9.,  8.,  4.,  3.,  7.,  0.]])

如果一個(gè)維度為的是-1, 那么reshape函數(shù)會(huì)自動(dòng)計(jì)算它的值。

>>> a
array([[ 7.,  8.,  0.,  9.,  8.,  4.],
       [ 9.,  8.,  4.,  3.,  7.,  0.]])

>>> a.reshape(3, -1)
array([[ 7.,  8.,  0.,  9.],
       [ 8.,  4.,  9.,  8.],
       [ 4.,  3.,  7.,  0.]])

數(shù)組合并

多個(gè)數(shù)組可以根據(jù)不同的軸組合在一起

>>> a = np.floor(10*np.random.random((2,2)))

>>> a
array([[ 1.,  1.],
       [ 4.,  4.]])

>>> b = np.floor(10*np.random.random((2,2)))

>>> b
array([[ 2.,  9.],
       [ 0.,  3.]])

>>> np.vstack((a, b))
array([[ 1.,  1.],
       [ 4.,  4.],
       [ 2.,  9.],
       [ 0.,  3.]])

>>> np.hstack((a,b))
array([[ 1.,  1.,  2.,  9.],
       [ 4.,  4.,  0.,  3.]])

column_stack函數(shù)把1維數(shù)組當(dāng)做列來拼成2維數(shù)組,如果只是操作2維數(shù)組,跟hstack的等效。

>>> a
array([[ 1.,  1.],
       [ 4.,  4.]])

>>> b
array([[ 2.,  9.],
       [ 0.,  3.]])

# 操作2維數(shù)組,等效于hstack
>>> np.column_stack((a, b))
array([[ 1.,  1.,  2.,  9.],
       [ 4.,  4.,  0.,  3.]])
       
>>> a = np.array([4., 2.])

>>> b = np.array([3., 8.])

# 操作1維數(shù)組,返回2維數(shù)組,a,b分別為2維數(shù)組的列
>>> np.column_stack((a, b))
array([[ 4.,  3.],
       [ 2.,  8.]])
       
>>> from numpy import newaxis
# 將1維數(shù)組變成2維數(shù)組
>>> a[:,newaxis]
array([[ 4.],
       [ 2.]])

# 都是操作二維數(shù)組,下面兩個(gè)操作column_stack和hstack等效
>>> np.column_stack((a[:, newaxis], b[:, newaxis]))
array([[ 4.,  3.],
       [ 2.,  8.]])

>>> np.hstack((a[:, newaxis], b[:, newaxis]))
array([[ 4.,  3.],
       [ 2.,  8.]])

另外不論什么數(shù)組,row_stack函數(shù)等效于vstack。通常來說,2維以上的數(shù)組,hstack基于第2根軸做運(yùn)算,vstack基于第1根軸,concatenate函數(shù)額外多接受一個(gè)參數(shù),可以指定基于哪根軸做數(shù)組的合并操作。

另外, r_c_函數(shù)對(duì)于在一個(gè)軸上組合數(shù)據(jù)相當(dāng)喲偶用,他們?cè)试S使用范圍符號(hào):

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

數(shù)組切割

使用hsplit函數(shù),你可以在水平方向切割一個(gè)數(shù)組

>>> a
array([[ 9.,  0.,  2.,  0.,  0.,  4.,  1.,  6.,  4.,  8.,  3.,  9.],
       [ 5.,  3.,  0.,  5.,  5.,  8.,  0.,  5.,  6.,  3.,  8.,  7.]])

# 切割成3個(gè)數(shù)組
>>> np.hsplit(a, 3)
[array([[ 9.,  0.,  2.,  0.],
        [ 5.,  3.,  0.,  5.]]), array([[ 0.,  4.,  1.,  6.],
        [ 5.,  8.,  0.,  5.]]), array([[ 4.,  8.,  3.,  9.],
        [ 6.,  3.,  8.,  7.]])]
        
 >>> np.vsplit(a, 2)
[array([[ 9.,  0.,  2.,  0.,  0.,  4.,  1.,  6.,  4.,  8.,  3.,  9.]]),
 array([[ 5.,  3.,  0.,  5.,  5.,  8.,  0.,  5.,  6.,  3.,  8.,  7.]])]

# 基于第3和第4列切割
>>> np.hsplit(a, (3,4))
[array([[ 9.,  0.,  2.],
        [ 5.,  3.,  0.]]), array([[ 0.],
        [ 5.]]), array([[ 0.,  4.,  1.,  6.,  4.,  8.,  3.,  9.],
        [ 5.,  8.,  0.,  5.,  6.,  3.,  8.,  7.]])]

vsplit可以基于垂直軸切割,array_split可以指定基于哪個(gè)軸切割

復(fù)制和視圖(Views)

當(dāng)進(jìn)行數(shù)組運(yùn)算和改變數(shù)組時(shí),有時(shí)候數(shù)據(jù)是被復(fù)制到一個(gè)新的數(shù)組,有時(shí)候不是。對(duì)于初學(xué)者來說,對(duì)于具體是哪種操作,很容易混淆。 主要分三種情況。

一點(diǎn)也不復(fù)制

>>> a = np.arange(12)

>>> b = a   # 不會(huì)有新對(duì)象產(chǎn)生

>>> b is a  # a和b是同一個(gè)數(shù)組
True

>>> b.shape
(12,)

>>> b.shape = 3, 4  # 改變b的shape, a也同樣變化

>>> a.shape       
(3, 4)

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

python中使用可變參數(shù)時(shí),可以看做是引用傳參,因此函數(shù)條用會(huì)產(chǎn)生新的數(shù)組

>>> def f(x):
...     print(id(x))
...

>>> id(a)
4361164320

>>> f(a)
4361164320

視圖(View)和淺復(fù)制(Shallow Copy)

不同的數(shù)組可以共享數(shù)據(jù),view函數(shù)可以創(chuàng)造一個(gè)數(shù)據(jù)相同的新數(shù)組

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

>>> c = a.view()

>>> c is a   # c和a不是同一個(gè)數(shù)組
False

>>> c.base is a  # c是a的數(shù)據(jù)的視圖
True

>>> c.flags.owndata
False

>>> c.shape = 2, 6  # a的不會(huì)改變

>>> a.shape
(3, 4)

>>> c[0, 4] = 1234  # a的數(shù)據(jù)發(fā)生改變

>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])

>>> c
array([[   0,    1,    2,    3, 1234,    5],
       [   6,    7,    8,    9,   10,   11]])

一個(gè)數(shù)組的切片返回的就是它的視圖

>>> a
array([[   0,    1,    2,    3],
       [1234,    5,    6,    7],
       [   8,    9,   10,   11]])

>>> s = a [:, 1:3]

>>> s
array([[ 1,  2],
       [ 5,  6],
       [ 9, 10]])

>>> s[:] = 10 # s[:]是s的視圖

>>> s
array([[10, 10],
       [10, 10],
       [10, 10]])

深度復(fù)制(Deep Copy)

copy方法可以完全復(fù)制數(shù)組和它的數(shù)據(jù)

>>> a = np.arange(12).reshape((3,4))

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

>>> d = a.copy()

>>> d is a
False

>>> d.base is a
False

>>> d[0, 0] = 9999

>>> d
array([[9999,    1,    2,    3],
       [   4,    5,    6,    7],
       [   8,    9,   10,   11]])

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

函數(shù)和方法概覽

如下是按照分類整理的常用函數(shù)和方法,完整的分類可以參考Routines

數(shù)組創(chuàng)建

  • arange
  • array
  • copy
  • empty
  • empty_like
  • eye # 創(chuàng)建一個(gè)對(duì)角線全是1的二維數(shù)組
  • fromfile
  • fromfunction
  • identity # 創(chuàng)建一個(gè)對(duì)角線全是1的方形矩陣,與eye方法差不多,只是可以接受的參數(shù)不同
  • linspace
  • logspace # 創(chuàng)建等比數(shù)列
  • mgrid
  • orgid
  • ones
  • ones_like
  • zeros
  • zeros_like

轉(zhuǎn)換

  • ndarray.astype # 改變數(shù)組的元素格式
  • atleast_1d # 將輸入轉(zhuǎn)換為至少1維數(shù)組
  • atleast_2d
  • alteast_3d
  • mat # 將輸入轉(zhuǎn)換為矩陣

處理

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

Questions

  • all
  • any
  • nonezero
  • where

排序

  • argmax # 返回最大值的索引
  • argmin # 返回最小值的索引
  • argsort # 返回排序后的索引
  • max
  • min
  • ptp
  • searchsorted
  • sort

運(yùn)算

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

基本統(tǒng)計(jì)

  • cov
  • mean
  • std
  • var

線性代數(shù)

  • cross
  • dot
  • outer
  • linalg
  • svd
  • vdot

Less Basic

廣播機(jī)制

屬于廣播主要描述于numpy對(duì)于不同shape的數(shù)組如何進(jìn)行算術(shù)運(yùn)算。受限于一些特定約束。
一般都是小的數(shù)組擴(kuò)展為大的數(shù)組,以便能計(jì)算。

通常情況下,numpy操作的數(shù)組必須是相同shape的。

>>> import numpy as np

>>> a = np.array([1.0, 2.0, 3.0])

>>> b = np.array([2.0, 2.0, 2.0])

>>> a * b
array([ 2.,  4.,  6.])

當(dāng)數(shù)組的shape滿足某些特定約束時(shí),numpy的廣播機(jī)制可以使這個(gè)約束更寬松。最簡(jiǎn)單的就是廣播例子就是當(dāng)數(shù)組和一個(gè)標(biāo)量操作時(shí)。

>>> a = np.array([1.0, 2.0, 3.0])

>>> b = 2.0

>>> a * b
array([ 2.,  4.,  6.])

上面兩個(gè)例子的結(jié)果是一樣的,我們可以認(rèn)為標(biāo)量b被擴(kuò)展為了和a同樣shape的數(shù)組,b中的新元素就是原來標(biāo)量的拷貝。這個(gè)擴(kuò)展策略僅僅是概念上的,實(shí)際上Numpy足夠聰明,能自動(dòng)使用標(biāo)量做運(yùn)算,而不需要復(fù)制任何東西。所以廣播運(yùn)算從計(jì)算內(nèi)存上來說更優(yōu)秀。

要能滿足廣播,必須符合下面兩條規(guī)則:

  1. 廣播之后,輸出數(shù)組的shape是輸入數(shù)組shape的各個(gè)軸上的最大值,然后沿著較大shape屬性的方向復(fù)制延伸;
  2. 要進(jìn)行廣播機(jī)制,要么兩個(gè)數(shù)組的shape屬性一樣,要么其中有一個(gè)數(shù)組的shape屬性必須有一個(gè)等于1;

更多可以參考:

索引

numpy除了支持普通的python方式的索引和切片之外,還支持整數(shù)數(shù)組或布爾數(shù)組索引

數(shù)組索引

>>> a = np.arange(12) ** 2

>>> i = np.array([1,1,3,8,5])

>>> a
array([  0,   1,   4,   9,  16,  25,  36,  49,  64,  81, 100, 121])

>>> i
array([1, 1, 3, 8, 5])

# 返回a中再索引i的元素
>>> a[i]
array([ 1,  1,  9, 64, 25])

>>> j = np.array([[3,4], [9,7]])

# 二維數(shù)組索引,返回a中在索引j的元素
>>> a[j]
array([[ 9, 16],
       [81, 49]])

當(dāng)數(shù)組索引作用在多維數(shù)組時(shí),是根據(jù)數(shù)組的第一個(gè)維度來索引的。

>>> palette = np.array([ [0 ,0, 0],
...                      [255, 0, 0],
...                      [0, 255, 0],
...                      [0, 0, 255],
...                      [255, 255, 255] ])
...

>>> image = np.array([ [0, 1, 2, 0],
...                    [0, 3, 4, 0] ])
...

>>> palette[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]]])

索引同樣可以是多維的,但是必須是相同的shape

>>> a = np.arange(12).reshape(3, 4)

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# indices for the first dim of a
>>> i = np.array([[0,1],
...                [1,2] ])
...

# indices for the second dim
>>> j = np.array([[2, 1],
...               [3, 3] ])
...

# i and j must have equal shape
# 返回的結(jié)果是是[ [a[0,2], a[1,1]
#                [a[1,3], a[2, 3] ]
>>> a[i, j]
array([[ 2,  5],
       [ 7, 11]])
       
# [ a[0,2], a[1, 2],
#   a[1,2], a[2, 2] ]       
>>> a[i, 2]
array([[ 2,  6],
       [ 6, 10]])
       
# [[[ a[0,2], a[0,1],
#     a[0,3], a[0,3]], 
#     
#     a[1,2], a[1,1],
#     a[1,3], a[1,3]],    
#     
#     a[2,2], a[2,1],
#     a[2,3], a[2,3]]] 
>>> a[:, j]
array([[[ 2,  1],
    [ 3,  3]],

   [[ 6,  5],
    [ 7,  7]],

   [[10,  9],
    [11, 11]]])

同樣,我們可以把ij放在一個(gè)列表里,然后用列表做索引

>>> l = [i, j]

# 等價(jià)于a[i, j]
>>> a[l]
array([[ 2,  5],
       [ 7, 11]])

但是,我們不可以把ij放在一個(gè)數(shù)組里,因?yàn)閿?shù)組索引是作用在第一個(gè)維度上的。

>>> s = np.array([i, j])

>>> s
array([[[0, 1],
        [1, 2]],

       [[2, 1],
        [3, 3]]])

>>> a[s]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-42-c057dc68e5fe> in <module>()
----> 1 a[s]

IndexError: index 3 is out of bounds for axis 0 with size 3

# 等價(jià)于 a[i, j]
>>> a[tuple(s)]
array([[ 2,  5],
       [ 7, 11]])

我們同樣可以給數(shù)組索引賦值

>>> a = np.arange(5)

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

>>> a[[1,3,4]] = 0

>>> a
array([0, 0, 2, 0, 0])

但是當(dāng)列表包含相同的索引時(shí),這個(gè)位置會(huì)被賦值多次,最終只保留最后一次的值

>>> a = np.arange(5)

>>> a[[0, 0, 2]] = [1,2,3]

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

上面看起來很合理,但是當(dāng)使用+=符號(hào)的時(shí)候,結(jié)果和我們想的可能不太一樣

>>> a = np.arange(5)

>>> a[[0, 0, 2]] += 1

>>> a
array([1, 1, 3, 3, 4])

盡管索引中出現(xiàn)了兩次0,但是第0個(gè)元素它只加了1次。

布爾數(shù)組索引

當(dāng)使用數(shù)字?jǐn)?shù)組索引時(shí),我們提供了哪些元素要被索引的信息。但是當(dāng)使用布爾數(shù)組時(shí),我們是明確哪些元素需要,哪些元素不需要。

>>> a = np.arange(12).reshape((3,4))

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

>>> b = a > 4

>>> b
array([[False, False, False, False],
       [False,  True,  True,  True],
       [ True,  True,  True,  True]], dtype=bool)

>>> a[b]
array([ 5,  6,  7,  8,  9, 10, 11]) 

這個(gè)特性非常適合用來賦值

# 所有大于4的元素都賦值為0
>>> a[b] = 0

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

一個(gè)使用布爾數(shù)組索引的例子就是曼德博集合(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()

另一個(gè)布爾數(shù)組的場(chǎng)景跟數(shù)字?jǐn)?shù)組索引類似,對(duì)每個(gè)維度,我們提供一個(gè)1維的數(shù)組來選擇我們需要的切片

>>> a = np.arange(12).reshape(3, 4)

>>> b1 = np.array([False, True, True])

>>> b2 = np.array([True, False, True, False])

>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# 選擇行
>>> a[b1, :]
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# 同上
>>> a[b1]
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# 選擇列
>>> a[:, b2]
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])

# a weird thing to do
>>> a[b1, b2]
array([ 4, 10])

ix_()函數(shù) (作用待定)

字符串索引

Numpy提供了創(chuàng)建結(jié)構(gòu)化的數(shù)組的能力,可以通過列名來操作數(shù)據(jù)

# dtype分別制定每一個(gè)的名字和數(shù)據(jù)類型
>>> x = np.array([(1, 2., 'Hello'), (2, 3., "World")], dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])

>>> x[1]
(2,  3., b'World')

>>> x['foo']
array([1, 2], dtype=int32)

>>> x['bar']
array([ 2.,  3.], dtype=float32)

>>> x['baz']
array([b'Hello', b'World'],
      dtype='|S10')

更多

  • Data types
  • Array creation
  • I/O with NumPy
  • Indexing
  • Broadcasting
  • Byte-swapping
  • Structured arrays
  • Subclassing ndarray

擴(kuò)展閱讀

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容