先決條件
在閱讀這個教程之前,你多少需要知道點python。如果你想重新回憶下彤悔,請看看Python Tutorial
如果你想要運行教程中的示例嘉抓,你需要在你的電腦上安裝了一些軟件,詳細內(nèi)容請查看
http://scipy.org/install.html
基礎(chǔ)篇
NumPy的主要對象是同種元素的多維數(shù)組晕窑。這是一個所有的元素都是一種類型抑片、通過一個正整數(shù)元組索引的元素表格(通常是元素是數(shù)字)。在NumPy中維度(dimensions)
叫做軸(axes)
杨赤,軸的個數(shù)叫做秩(rank)
敞斋。
例如,在3D空間一個點的坐標
[1, 2, 3]
是一個秩為1的數(shù)組望拖,因為它只有一個軸,且軸長度為3挫鸽。
例如说敏,
[[ 1., 0., 0.],
[ 0., 1., 2.]]
以上例子中,數(shù)組的秩為2(它有兩個維度)丢郊。第一個維度長度為2盔沫,第二個維度長度為3。
NumPy的數(shù)組類被稱作ndarray
枫匾。通常被稱作數(shù)組(array)
架诞。注意numpy.array
和標準Python庫類array.array
并不相同,后者只處理一維數(shù)組和提供少量功能干茉。更多重要ndarray
對象屬性有:
ndarray.ndim
數(shù)組軸(axes)的個數(shù)谴忧,在python的世界中,軸的個數(shù)被稱作秩(rank)
ndarray.shape
數(shù)組的維度(dimensions)角虫。這是一個指示數(shù)組在每個維度上大小的整數(shù)元組沾谓。
例如一個n排m列的矩陣,它的
shape
屬性將是(n,m)
戳鹅,這個元組的長度顯然是秩(rank)均驶,即維度(dimensions)或者ndim
屬性
ndarray.size
數(shù)組元素的總個數(shù),等于shape
屬性中元組元素的乘積枫虏。
ndarray.dtype
一個用來描述數(shù)組中元素類型的對象妇穴,可以通過創(chuàng)造或指定dtype使用標準Python類型。另外NumPy提供它自己的數(shù)據(jù)類型隶债。numpy.int32, numpy.int16, numpy.float64等等腾它。
ndarray.itemsize
數(shù)組中每個元素的字節(jié)大小。
例如死讹,一個元素類型為
float64
的數(shù)組itemsize
屬性值為8(=64/8)
又如携狭,一個元素類型為
complex32
的數(shù)組itemsize
屬性為4(=32/8)。和ndarray.dtype.itemsize
值相同回俐。
ndarray.data
包含實際數(shù)組元素的緩沖區(qū)逛腿,通常我們不需要使用這個屬性稀并,因為我們總是通過索引來使用數(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]])
>>> 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'>
創(chuàng)建數(shù)組(array)
有好幾種創(chuàng)建數(shù)組的方法单默。例如碘举,你可以使用array
函數(shù)從常規(guī)的Python列表和元組創(chuàng)造數(shù)組。所創(chuàng)建的數(shù)組類型由原序列中的元素類型推導而來搁廓。
>>> 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')
一個常見的錯誤包括用多個數(shù)值參數(shù)調(diào)用array
而不是提供一個由數(shù)值組成的列表作為一個參數(shù)引颈。
>>> a = array(1,2,3,4) # WRONG
>>> a = array([1,2,3,4]) # RIGHT
array
函數(shù)將 序列內(nèi)含序列(sequences of sequences)
轉(zhuǎn)化成二維的數(shù)組,序列內(nèi)含序列內(nèi)含序列(sequences of sequences of sequences)
轉(zhuǎn)化成三維數(shù)組等等境蜕。
>>> b = np.array([(1.5,2,3), (4,5,6)])
>>> b
array([[ 1.5, 2. , 3. ],
[ 4. , 5. , 6. ]])
數(shù)組類型可以在創(chuàng)建時顯示指定
>>> c = np.array( [ [1,2], [3,4] ], dtype=complex )
>>> c
array([[ 1.+0.j, 2.+0.j],
[ 3.+0.j, 4.+0.j]])
通常蝙场,數(shù)組的元素開始都是未知的,但是它的大小已知粱年。因此售滤,NumPy提供了一些使用占位符創(chuàng)建數(shù)組的函數(shù)。這最小化了擴展數(shù)組的需要和高昂的運算代價台诗。
函數(shù)zeros
創(chuàng)建一個全是0的數(shù)組完箩,函數(shù)ones
創(chuàng)建一個全1的數(shù)組,函數(shù)empty
創(chuàng)建一個內(nèi)容隨機并且依賴內(nèi)存狀態(tài)的數(shù)組拉队。默認創(chuàng)建的數(shù)組類型(dtype)都是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]])
為了創(chuàng)建一個數(shù)列,NumPy提供一個類似arange
的函數(shù)返回數(shù)組而不是列表
>>> 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
使用浮點數(shù)參數(shù)時粱快,由于浮點數(shù)精度有限秩彤,通常無法預測獲得的元素個數(shù)。因此事哭,最好使用函數(shù)linspace
去接收我們想要的元素個數(shù)來代替指定步長呐舔。
補充
>>> numpy.linspace(-1, 0, 5) array([-1. , -0.75, -0.5 , -0.25, 0. ])
參考 array,zeros,zeros_like,ones,ones_like,empty,empty_like,arange,linspace,numpy.random.rand,numpy.random.randn,fromfunction,fromfile
打印數(shù)組
當你打印一個數(shù)組,NumPy以類似嵌套列表的形式顯示它慷蠕,但是呈以下布局:
- 最后的軸從左到右打印
- 次后的軸從頂向下打印
- 剩下的軸從頂向下打印珊拼,每個切片通過一個空行與下一個隔開
一維數(shù)組被打印成行,二維數(shù)組成矩陣流炕,三維數(shù)組成矩陣列表澎现。
>>> 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]]]
查看下面獲得有關(guān)reshape
的更多細節(jié)。
如果一個數(shù)組用來打印太大了每辟,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的這種行為并強制打印整個數(shù)組剑辫,你可以設(shè)置set_printoptions
參數(shù)來更改打印選項。
>>> np.set_printoptions(threshold='nan')
基礎(chǔ)運算
數(shù)組的算術(shù)運算是按元素的渠欺。新的數(shù)組被創(chuàng)建并且被結(jié)果填充妹蔽。
>>> 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
函數(shù)或創(chuàng)建矩陣對象實現(xiàn):
>>> 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]])
有些操作符像+=
和*=
被用來更改已存在數(shù)組而不創(chuàng)建一個新的數(shù)組胳岂。
>>> 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'
當運算的是不同類型的數(shù)組時编整,結(jié)果數(shù)組類型和更普遍或更精確相同(這種行為叫做upcasting)。
>>> 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'
許多一元運算乳丰,如計算數(shù)組所有元素之和掌测,都用ndarray
類的方法來實現(xiàn)。
>>> 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
通常产园,這些運算將數(shù)組看作是一維線性列表汞斧,忽略原有形狀(shape)。但可通過指定axis
參數(shù)(即數(shù)組的軸)對指定的軸做相應(yīng)的運算:
>>> 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]) #如果axis是1什燕,就計算第二軸的值粘勒,就是行相加,結(jié)果是array([ 6, 22, 38])
>>>
>>> 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]])
通用函數(shù)
NumPy提供常見的數(shù)學函數(shù)如sin屎即,cos和exp庙睡。在NumPy中,這些叫作“通用函數(shù)(universal functions)”(ufunc
)剑勾。在NumPy里這些函數(shù)按數(shù)組的元素運算埃撵,產(chǎn)生一個數(shù)組作為輸出赵颅。
>>> 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
索引虽另,切片和迭代
一維數(shù)組可以被索引、切片和迭代饺谬,就像列表(lists)和其它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
多維數(shù)組可以每個軸有一個索引。這些索引由一個逗號分割的元組給出:
>>> 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]])
當少于軸數(shù)的索引被提供時募寨,缺失的索引被認為是整個切片:
>>> b[-1] # the last row. Equivalent to b[-1,:]
array([40, 41, 42, 43])
b[i]
中括號中的表達式被當作i
和一系列:
族展,來代表剩下的軸。NumPy也允許你像b[i,...]
來寫拔鹰。
點(…
)代表許多產(chǎn)生一個完整的索引元組必要的分號仪缸。如果x
是秩為5的數(shù)組(即它有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]])
迭代(Iterating)多維數(shù)組是就第一個軸而言的:
>>> 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]
但是列肢,如果一個人想對每個數(shù)組中元素進行運算恰画,我們可以使用flat
屬性,該屬性是數(shù)組所有元素的一個迭代器:
>>> 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
變形操作
更改數(shù)組的形狀
一個數(shù)組的形狀由它每個軸上的元素個數(shù)給出:
>>> 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)
一個數(shù)組的形狀可以被多種命令修改瓷马。注意下面三種命令都返回一個被修改的數(shù)組拴还,并沒有改變原來的數(shù)組:
>>> 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 轉(zhuǎn)置
array([[ 2., 4., 8.],
[ 8., 5., 9.],
[ 0., 1., 3.],
[ 6., 1., 6.]])
>>> a.T.shape
(4, 3)
>>> a.shape
(3, 4)
由ravel()展平的數(shù)組元素的順序通常是“C風格”的,就是說欧聘,最右邊的索引變化得最快片林,所以元素a[0,0]之后是a[0,1]。如果數(shù)組被改變形狀(reshape)成其它形狀,數(shù)組仍然是“C風格”的费封。NumPy通常創(chuàng)建一個以這個順序保存數(shù)據(jù)的數(shù)組焕妙,所以ravel()將總是不需要復制它的參數(shù)。但是如果數(shù)組是通過切片其它數(shù)組或有不同尋常的選項時孝偎,它可能需要被復制访敌。函數(shù)reshape()和ravel()還可以被同過一些可選參數(shù)構(gòu)建成FORTRAN風格的數(shù)組,即最左邊的索引變化最快衣盾。
reshape
函數(shù)改變參數(shù)形狀并返回它寺旺,而ndarray.resize
函數(shù)改變數(shù)組自身。
>>> 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.]])
組合(stack)不同的數(shù)組
幾個數(shù)組可以沿不同的軸組合在一起:
>>> 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.]])
函數(shù)column_stack以列將一維數(shù)組合成二維數(shù)組阻塑,它等同于vstack僅對一維數(shù)組。
>>> 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.]])
對那些維度比二維更高的數(shù)組果复,hstack沿著第二個軸組合陈莽,vstack沿著第一個軸組合,concatenate允許可選參數(shù)給出組合時沿著的軸虽抄。
Note
在復雜情況下走搁,r_和c_對創(chuàng)建沿著一個方向組合的數(shù)很有用,它們允許范圍符號(“:”):
>>> np.r_[1:4,0,4]
array([1, 2, 3, 0, 4])
當使用數(shù)組作為參數(shù)時迈窟,r_和c_的默認行為和vstack和hstack很像私植,但是允許可選的參數(shù)給出組合所沿著的軸的序號。
將一個數(shù)組分割(split)成幾個小數(shù)組
使用hsplit你能將數(shù)組沿著它的水平軸分割车酣,或者指定返回相同形狀數(shù)組的個數(shù)曲稼,或者指定在哪些列后發(fā)生分割:
>>> 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.]])]
vsplit沿著縱向的軸分割,array_split允許指定沿哪個軸分割湖员。
復制和視圖
當運算和處理數(shù)組時贫悄,它們的數(shù)據(jù)有時被拷貝到新的數(shù)組有時不是。這通常是新手困惑的地方娘摔。這有三種情況:
完全不拷貝
簡單的賦值不拷貝數(shù)組對象或它們的數(shù)據(jù)窄坦。
>>> 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傳遞不定對象時只傳遞對象引用,所以函數(shù)調(diào)用不拷貝數(shù)組凳寺。
>>> def f(x):
... print(id(x))
...
>>> id(a) # id is a unique identifier of an object
148293216
>>> f(a)
148293216
視圖(View)或淺復制(Shallow Copy)
不同的數(shù)組對象可以共享同一數(shù)據(jù)鸭津。視圖(view
)方法創(chuàng)造一個新的數(shù)組對象指向同一數(shù)據(jù)。
>>> 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]])
切片數(shù)組返回它的一個視圖:
>>> 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]])
深復制(Deep Copy)
復制(copy
)方法完全復制數(shù)組和它的數(shù)據(jù)读第。
>>> 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]])
函數(shù)和方法總覽
這是個NumPy函數(shù)和方法分類排列目錄曙博。 查看Routines完整列表。
Array Creation
arange,array,copy,empty,empty_like,eye,fromfile,fromfunction,identity,linspace,logspace,mgrid,ogrid,ones,ones_like,r,zeros,zeros_like
Conversions
ndarray.astype,atleast_1d,atleast_2d,atleast_3d,mat
Manipulations
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,nonzero,where
Ordering
argmax,argmin,argsort,max,min,ptp,searchsorted,sort
Operations
choose,compress,cumprod,cumsum,inner,ndarray.fill,imag,prod,put,putmask,real,sum
Basic Statistics
cov,mean,std,var
Basic Linear Algebra
cross,dot,outer,linalg.svd,vdot
進階
廣播法則(rule)
廣播法則能使通用函數(shù)有意義地處理不具有相同形狀的輸入怜瞒。
廣播第一法則是父泳,如果所有的輸入數(shù)組維度不都相同般哼,一個“1”將被重復地添加在維度較小的數(shù)組上直至所有的數(shù)組擁有一樣的維度。
廣播第二法則確定長度為1的數(shù)組沿著特殊的方向表現(xiàn)地好像它有沿著那個方向最大形狀的大小惠窄。對數(shù)組來說蒸眠,沿著那個維度的數(shù)組元素的值理應(yīng)相同。
應(yīng)用廣播法則之后杆融,所有數(shù)組的大小必須匹配楞卡。更多細節(jié)可以從這個文檔找到。
花哨的索引和索引技巧
NumPy比普通Python序列提供更多的索引功能脾歇。除了索引整數(shù)和切片蒋腮,正如我們之前看到的,數(shù)組可以被整數(shù)數(shù)組和布爾數(shù)組索引藕各。
通過數(shù)組索引
>>> 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]])
當被索引數(shù)組a
是多維的時池摧,每一個唯一的索引數(shù)列指向a
的第一維。以下示例通過將圖片標簽用調(diào)色版轉(zhuǎn)換成色彩圖像展示了這種行為激况。
>>> 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]]])
我們也可以給出不不止一維的索引作彤,每一維的索引數(shù)組必須有相同的形狀部念。
>>> 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
放到序列中(比如說列表)然后通過list索引幸斥。
>>> l = [i,j]
>>> a[l] # equivalent to a[i,j]
array([[ 2, 5],
[ 7, 11]])
然而剔交,我們不能把i
和j
放在一個數(shù)組中,因為這個數(shù)組將被解釋成索引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]])
另一個常用的數(shù)組索引用法是搜索時間序列最大值译荞。
>>> 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
你也可以使用數(shù)組索引作為目標來賦值:
>>> 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的+=
結(jié)構(gòu)奋岁,可能結(jié)果并非你所期望:
>>> a = np.arange(5)
>>> a[[0,0,2]]+=1
>>> a
array([1, 1, 3, 3, 4])
即使0在索引列表中出現(xiàn)兩次,索引為0的元素僅僅增加一次荸百。這是因為Python要求a+=1和a=a+1等同闻伶。
通過布爾數(shù)組索引
當我們使用整數(shù)數(shù)組索引數(shù)組時,我們提供一個索引列表去選擇够话。通過布爾數(shù)組索引的方法是不同的我們顯式地選擇數(shù)組中我們想要和不想要的元素蓝翰。
我們能想到的使用布爾數(shù)組的索引最自然方式就是使用和原數(shù)組一樣形狀的布爾數(shù)組。
>>> 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]])
你可以參考曼德博集合示例看看如何使用布爾索引來生成曼德博集合的圖像女嘲。
>>> 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()
第二種通過布爾來索引的方法更近似于整數(shù)索引畜份;對數(shù)組的每個維度我們給一個一維布爾數(shù)組來選擇我們想要的切片:
>>> 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])
注意一維數(shù)組的長度必須和你想要切片的維度或軸的長度一致,在之前的例子中欣尼,b1
是一個秩為1長度為3的數(shù)組(a
的行數(shù))爆雹,b2
(長度為4)與a
的第二秩(列)相一致停蕉。
ix_()函數(shù)
ix_函數(shù)可以為了獲得的結(jié)果而用來結(jié)合不同向量。例如钙态,如果你想要用所有向量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]]])
這個reduce與ufunc.reduce(比如說add.reduce)相比的優(yōu)勢在于它利用了廣播法則,避免了創(chuàng)建一個輸出大小乘以向量個數(shù)的參數(shù)數(shù)組册倒。
用字符串索引
線性代數(shù)
繼續(xù)前進蚓挤,基本線性代數(shù)包含在這里。
簡單數(shù)組計算
參考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]`` .
技巧和建議
在這里我們給出一些短而且有用的建議
“自動”變形
要改變一個數(shù)組的維度驻子,你可以漏掉一個可以被自動推斷出來的大小
>>> 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]]])
向量疊加
怎樣通過相同大小的向量構(gòu)建一個二維數(shù)組灿意?MATLAB里面很容易:如果x
和y
是兩個相同長度的向量,你只要m=[x;y]
崇呵。在NumPy中可以通過函數(shù)column_stack
, dstack
, hstack
和 vstack
脾歧,取決于在哪個維度疊加,例如:
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])
這些方法的邏輯用在多于兩個維度的地方會很奇怪演熟。
直方圖(histogram)
NumPy中·histogram·函數(shù)應(yīng)用到一個數(shù)組返回一對向量:直方圖數(shù)組和箱式向量鞭执。注意:matplotlib
也有一個用來建立直方圖的函數(shù)(叫作hist
,正如matlab中一樣)與NumPy中的不同。主要的差別是pylab.hist
自動繪制直方圖芒粹,而numpy.histogram
僅僅產(chǎn)生數(shù)據(jù)
>>> 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()