參考:
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ù)組
arrayzeros-
zeros_like# 創(chuàng)建一個(gè)和給定數(shù)組相同shape的全是0的數(shù)組 onesones_likeemptyempty_likearangelinspace-
numpy.random.rand# 從 [0, 1) 中返回一個(gè)或多個(gè)樣本值。 -
numpy.random.randn# 從標(biāo)準(zhǔn)正態(tài)分布中返回一個(gè)或多個(gè)樣本值。 fromfunctionfromfile
打印數(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ī)則:
- 廣播之后,輸出數(shù)組的shape是輸入數(shù)組shape的各個(gè)軸上的最大值,然后沿著較大shape屬性的方向復(fù)制延伸;
- 要進(jìn)行廣播機(jī)制,要么兩個(gè)數(shù)組的shape屬性一樣,要么其中有一個(gè)數(shù)組的shape屬性必須有一個(gè)等于1;
更多可以參考:
- https://docs.scipy.org/doc/numpy-dev/user/basics.broadcasting.html
- http://www.labri.fr/perso/nrougier/from-python-to-numpy/?utm_source=mybridge&utm_medium=blog&utm_campaign=read_more#broadcasting
索引
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]]])
同樣,我們可以把i和j放在一個(gè)列表里,然后用列表做索引
>>> l = [i, j]
# 等價(jià)于a[i, j]
>>> a[l]
array([[ 2, 5],
[ 7, 11]])
但是,我們不可以把i和j放在一個(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