[python][科學計算][numpy]使用指南

最後一次更新日期: 2019/4/13python

NumPy 是一個 Python 包。 它表明 「Numeric Python」。 它是一個由多維數組對象(ndarray)和用於處理數組的例程集合組成的庫。 使用NumPy,開發人員能夠執行如下操做:git

  • 數組的算數和邏輯運算。
  • 傅立葉變換和用於圖形操做的例程。
  • 與線性代數有關的操做。 NumPy 擁有線性代數和隨機數生成的內置函數。

使用前先導入模塊: import numpy as npapi

點擊下方連接可前往各小節數組

使用指南1 - 屬性 (數據類型,形狀,維數,元素數,元素大小,字節數,順序)數據結構

使用指南2 - 建立 (從已有數據建立,快速填充)app

使用指南3 - 運算 (數組/集合/位/字符串/統計/線性代數運算,常量,廣播)less

使用指南4 - 查找 (索引,遍歷,抽樣,視圖)dom

使用指南5 - 變動 (更新,擴增,刪除)ide

使用指南6 - 重構 (類型轉換,重塑,排序,去重,拆分)函數

使用指南7 - 讀寫 (保存,讀取)

使用指南8 - 其餘 (矩陣類型,張量運算,傅里葉變換,圖像處理)

一. 屬性

返回目錄

1. 數據類型

ndarray.dtype

numpy經常使用數據類型

dtype type 類型名 說明
np.dtype('bool') np.bool_ 布爾類型 True or False
np.dtype('int8' | 'i1' | 'b') np.int8 8位整數(字節) -2^7 to 2^7-1
np.dtype('int16' | 'i2') np.int16 16位整數 -2^15 to 2^15-1
np.dtype('int32' | 'i4' | 'int' | 'i') np.int32 32位整數 -2^31 to 2^31-1
np.dtype('int64' | 'i8') np.int64 64位整數 -2^63 to 2^63-1
np.dtype('uint8' | 'u1' | 'B') np.uint8 8位無符號整數 0 to 2^8-1
np.dtype('uint16' | 'u2') np.uint16 16位無符號整數 0 to 2^16-1
np.dtype('uint32' | 'u4' | 'uint') np.uint32 32位無符號整數 0 to 2^32-1
np.dtype('uint64' | 'u8') np.uint64 64位無符號整數 0 to 2^64-1
np.dtype('float16' | 'f2') np.float16 半精度浮點數 1符號位+5指數位+10尾數位
np.dtype('float32' | 'f4' | 'f') np.float32 單精度浮點數 1符號位+8指數位+23尾數位
np.dtype('float64' | 'f8' | 'float' | 'd') np.float64 雙精度浮點數 1符號位+11指數位+52尾數位
np.dtype('complex64' | 'c8') np.complex64 64位複數 雙32位浮點數(實部+虛部)
np.dtype('complex128' | 'complex' | 'c16') np.complex128 128位複數 雙64位浮點數(實部+虛部)
np.dtype('object' | 'O') object 對象 可用於存儲引用類型
np.dtype('string_' | 'S' | 'S1' | 'S2' ...) np.bytes_ 定長字符串 須要聲明長度
np.dtype('unicode' | 'U' | 'U1' | 'U2' ...) np.str_ 定長Unicode字符串 須要聲明長度
np.dtype('datetime64' | 'M') np.datetime64 日期時間 可指定日期單位

注:同一種dtype能夠經過多種字符串標識去聲明的,見 | 分割的多項。 python的基本數據類型可被numpy識別,轉換爲對應類別下的默認類型,int對應np.int32float對應np.float64complex對應np.complex128

dtype與type的轉換

獲取dtype的type:dtype.type 經過type建立dtype:dtype(type)

dtype與type能夠直接進行比較

np.dtype('int')==np.int32

dtype的字節順序

np.dtype('<i8')

字節順序是經過對數據類型預先設定"<"或">"來決定的。"<"意味着小端法(最小值存儲在最小的地址,即低位組放在最前面)。">"意味着大端法(最重要的字節存儲在最小的地址,即高位組放在最前面)。通常狀況下采用默認設置便可。

2. 元素個數

ndarray.size

3. 元素的子節大小

ndarray.itemsize

由數據類型決定,每8位爲1字節。

4. 總字節數

ndarray.nbytes

由size和itemsize計算獲得。

5. 維數

ndarray.ndim

ndarray的每個維度被描述爲軸(axis),維數即軸的個數,軸的編號從0開始。

6. 形狀

ndarray.shape

tuple類型,每一位對應到每一個軸,例如0軸方向長爲10個元素,1軸方向長爲5個元素的數組形狀爲(10,5)

7. 內存佈局

numpy有兩種數據存儲的方式,一種是C-order,即行序優先,另外一種是Fortran-order,即列序優先,未顯式指定時默認C-order。因爲內部的優化機制,多數狀況下二者在使用時沒有明顯區別,通常不須要更改默認設置。 但在使用諸如迭代器之類的方法時,可經過order參數指定元素訪問順序,其中'C'指代C-order,'F'指代F-order。

二. 建立

返回目錄

1. 從已有數據建立

(1). 從list建立

#一維數組
a1=np.array([1,2])
#二維數組
a2=np.array([[1.,2.],[3.,4.]])
#三維數組
a3=np.array([[[1,2],[3,4]],[[5,6],[7,8]]],dtype='float')
#以此類推
複製代碼

從嵌套的序列結構建立多維數組時,最外面的一層對應數組第一個軸,以此類推。 第二個參數dtype能夠顯式聲明數組的數據類型,可傳入dtypetype(python基礎數據類型或numpy數據類型)或與dtype對應的字符串標識,不聲明的狀況下會根據傳入數據自動採用最合適的數據類型。

(2). 從tuple建立

a=np.array((1,2))
複製代碼

list是同樣,listtuple的嵌套同理。

(3). 從dict建立(不合適)

np.array({"x1":1,"x2":2})
Out[138]: array({'x1': 1, 'x2': 2}, dtype=object)
複製代碼

沒法正常轉換,整個dict會做爲一個對象存入數組,能夠嘗試用pandas庫去處理。

(4). 從其餘類數組結構中建立,如PIL的圖片類型

from PIL import Image
image= Image.open("D:\\test.jpg")
a=np.asarray(image)
複製代碼

np.asarray在多數狀況下與np.array等效,區別在於np.asarray會避免沒有必要的重複建立,當數據源一樣是ndarraydtype無變化時,不會返回新的數組。

2. 快速填充

(1). 0/1填充

#填充0
a1=np.zeros((2,2))
#填充1
a2=np.ones((2,2))
#聲明類型
a2=np.ones((2,2),dtype='int')
複製代碼

第一個參數shape爲數組形狀,必須賦值; 默認數據類型爲float64,可經過dtype參數指定類型。

(2). 對角矩陣

np.eye(3,3,0)
Out[151]: 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

np.eye(3,3,1)
Out[150]: 
array([[ 0.,  1.,  0.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  0.]])
複製代碼

第一個參數N爲0軸長度,必須賦值; 第二個參數M爲1軸長度,不賦值時與N值一致; 第一個參數k爲對角線偏移量,默認0,正數向上偏移,負數向下偏移。 對角矩陣固定爲二維數組。

(3).單位矩陣

np.identity(1)
Out[5]: array([[ 1.]])

np.identity(2)
Out[6]: 
array([[ 1.,  0.],
       [ 0.,  1.]])
複製代碼

第一個參數n爲統一的軸長度,必須賦值; 單位矩陣固定爲二維數組。

(4). 指定值填充

a=np.full((2,2),'a')
複製代碼

第一個參數shape爲數組形狀,必須賦值; 第二個參數fill_value爲填充值,必須賦值。

(5). 空值填充

a=np.empty((2,2))
複製代碼

第一個參數shape爲數組形狀,必須賦值。 建立一個數組,但不初始化其中的值。

(6). 參考已有數組形狀建立

a=np.ones((2,2))
a2=np.zeros_like(a)
a3=np.full_like(a,'a')
複製代碼

(7). 等差數列

#方法一
a1=np.arange(0,100,1)
#方法二
a2=np.linspace(0,99,100)
複製代碼

方法一,相似range函數,默認int類型, 三個參數分別爲:開始,結束,步長(區間前閉後開); 方法二,線性空間,默認float類型, 和range不同,結束值默認是包含於區間的, 且第三個參數不是步長而是元素個數。

(8). 隨機數

浮點數隨機數
#[0,1]浮點隨機數
a1=np.random.rand(5,5)
#標準正太分佈隨機數
a2=np.random.randn(5,5)
複製代碼

須要注意的是,上面的方法不經過shape而經過所有參數來定義數組形狀。

整數隨機數
#產生指定範圍的整數隨機數
a=np.random.randint(0,10,(4,3))
複製代碼

第一個參數low表示區間下限,必須賦值; 第二個參數high表示區間上限,未賦值時會將low做爲上限,0做爲下限; 第三個參數size表示數組形狀,未賦值時函數會返回標量值。

正態分佈隨機數
a=np.random.normal(100,10,(4,3))
複製代碼

第一個參數loc表示分佈的平均值; 第二個參數scale表示分佈的標準誤差; 第三個參數size表示數組形狀,未賦值時函數會返回標量值。

均勻分佈隨機數
a=np.random.uniform(0,10,(4,3))
複製代碼

第一個參數low表示區間下限,必須賦值; 第二個參數high表示區間上限,未賦值時會將low做爲上限,0做爲下限; 第三個參數size表示數組形狀,未賦值時函數會返回標量值。

泊松分佈隨機數
a=np.random.poisson(1.0,(4,3))
複製代碼

第一個參數lam是lambda係數; 第二個參數size表示數組形狀,未賦值時函數會返回標量值。

(9). 網格數據

X,Y=np.mgrid[1:2:2j,1:3:3j]

X
Out[27]: 
array([[ 1.,  1.,  1.],
       [ 2.,  2.,  2.]])

Y
Out[28]: 
array([[ 1.,  2.,  3.],
       [ 1.,  2.,  3.]])

x=np.array([1,2,3])
y=np.array([1,2])
X,Y=np.meshgrid(x,y)

X
Out[36]: 
array([[1, 2, 3],
       [1, 2, 3]])

Y
Out[37]: 
array([[1, 1, 1],
       [2, 2, 2]])
複製代碼

np.mgrid經過索引選取的方式直接得到網格數據,j表示步數且包含中止值,去掉j該項表明步長且不包含中止值,第一個索引位聲明X在軸0方向上的增加,第二個索引位聲明Y在軸1方向上的增加,而後將XY廣播至相同大小,存在更多索引位時以此類推。 np.meshgrid在已有數據基礎上構造網格數據,跟mgrid不同,第一個參數是表示第二個軸方向上增加的向量,第二個參數對應第一個軸,第三個參數對應第三個軸,第四個參數對應第四個軸,以後以此類推。 網格數據經常使用於繪圖。

(10). 複製

a1=np.zeros((2,2))
a2=np.copy(a1)
複製代碼

三. 運算

返回目錄

1. 運算符

numpy對python中的運算符做了重載,可經過一樣的用法實現數組運算。

數組與標量值的運算

a=np.arange(0, 4)

a
Out[192]: array([0, 1, 2, 3])

a+1
Out[193]: array([1, 2, 3, 4])

a*2
Out[194]: array([0, 2, 4, 6])
複製代碼

數組與數組的運算

a1=np.arange(0, 4);a2=np.arange(4, 8)

a1,a2
Out[200]: (array([0, 1, 2, 3]), array([4, 5, 6, 7]))

a1+a2
Out[201]: array([ 4,  6,  8, 10])

a2**a1
Out[202]: array([  1,   5,  36, 343], dtype=int32)
複製代碼

2. 標量值函數

標量值函數會對數組中每個元素進行一樣的計算。

一元函數

函數 做用 說明
np.abs 絕對值 計算浮點數/整數/複數的絕對值
np.fabs 絕對值 計算浮點數/整數的絕對值,速度更快(?)
np.sqrt 平方根 x^0.5
np.square 平方 x^2
np.log 天然對數 -
np.log2 2爲底的對數 -
np.log10 10爲底的對數
np.log1p x+1的天然對數 用於數值太小時保證計算的有效性
np.ceil 向上取整 -
np.floor 向下取整 -
np.rint 舍入取整 -
np.around 舍入指定位數 第二個參數decimals爲舍入位數
np.exp 天然指數 e^x
np.sign 符號值 三種值:1(正)、0(0)、-1(負)
np.modf 拆分小數和整數部分 以兩個獨立的數組方式返回
np.isnan 判斷是否爲NaN 返回bool型數組
np.isfinite 判斷是不是有窮 值非inf,非NaN;返回bool型數組
np.isinf 判斷是不是有窮 值爲inf或-inf;返回bool型數組
np.sin,np.sinh 正弦,雙曲正弦 -
np.cos,np.cosh 餘弦,雙曲餘弦 -
np.tan,np.tanh 正切,雙曲正切 -
np.arcsin,np.arcsinh 反正弦,反雙曲正弦 -
np.arccos,np.arccosh 反餘弦,反雙曲餘弦 -
np.arctan,np.arctanh 反正切,反雙曲正切 -
np.logical_not 邏輯非 -

多元函數

函數 做用 說明
np.add(a1,a2) 相加 a1+a2
np.sub(a1,a2) 相減 a1-a2
np.multiply(a1,a2) 相乘 a1*a2
np.divide(a1,a2) 相除 a1/a2
np.power(a1,a2) 乘冪 a1**a2
np.floor_divide(a1,a2) 整除 a1//a2
np.mod(a1,a2) 取模 a1%a2
np.maxinum(a1,a2,a3) 最大值 逐個元素進行比較,返回所有最大值的數組
np.fmax(a1,a2,a3) 最大值(忽略NaN) 逐個元素進行比較,返回所有最大值的數組
np.mininum(a1,a2,a3) 最小值 逐個元素進行比較,返回所有最小值的數組
np.fmin(a1,a2,a3) 最小值(忽略NaN) 逐個元素進行比較,返回所有最小值的數組
np.copysign(a1,a2) 複製符號 將a2的符號複製到a1中
np.greater(a1,a2) 大於 a1>a2
np.greater_equal(a1,a2) 大於等於 a1>=a2
np.less(a1,a2) 小於 a1<a2
np.less_equal(a1,a2) 小於等於 a1<=a2
np.equal(a1,a2) 等於 a1==a2
np.not_equal(a1,a2) 不等於 a1!=a2
np.logical_and(a1,a2) 邏輯與 -
np.logical_or(a1,a2) 邏輯或 -
np.logical_xor(a1,a2) 邏輯異或 -

3. 聚合函數

聚合函數會減小數組的維數,一般能夠指定一個軸方向axis進行聚合,結果數組會減小一個維度,不指定方向時會在全部軸方向上聚合,結果爲一個標量值。 大多數既能夠靜態調用,也能夠直接調用ndarray對象的方法。

函數 做用 說明
np.sum 求和 -
np.mean 平均值 -
np.max 最大值 -
np.min 最小值 -
np.prod 連乘 -
np.any 至少一個爲True 返回True/False
np.all 所有爲True 返回True/False

np.maxnp.min有對應的np.argmaxnp.argmin的方法用於返回索引,詳見查找章節。

(如下是部分示例)

np.sum

a=np.array([[1,3],[4,2]])

a
Out[314]: 
array([[1, 3],
       [4, 2]])

a.sum()
Out[315]: 10

a.sum(axis=0)
Out[316]: array([5, 5])

a.sum(axis=1)
Out[317]: array([4, 6])
複製代碼

np.all

a=np.array([[True,False],[True,True]])

a
Out[323]: 
array([[ True, False],
       [ True,  True]], dtype=bool)

a.all()
Out[324]: False

a.all(axis=0)
Out[325]: array([ True, False], dtype=bool)
複製代碼

4. 複合統計函數

函數 做用 說明
np.cumsum 累加 -
np.cumprod 累乘 -
np.std 標準差 ((a-a.mean())**2).sum()/a.size
np.var 方差 np.sqrt(((a-a.mean())**2).sum()/a.size)
np.average 加權平均數 第三個參數weights爲權重;ndarray無對應方法
np.bincount 分箱計數 只支持整數,分箱區間根據最大最小值自動生成,間隔爲1
np.histogram 直方圖統計 第二個參數bins指定分箱方式,比np.bincount更靈活

(如下是部分示例)

np.cumsum

a=np.array([[1,3],[4,2]])

a.cumsum()
Out[319]: array([ 1,  4,  8, 10], dtype=int32)

a.cumsum(axis=0)
Out[320]: 
array([[1, 3],
       [5, 5]], dtype=int32)
複製代碼

np.average

a=np.array([[1,3],[4,2]])
w=np.array([[0.4,0.1],[0.2,0.3]])

np.average(a)
Out[333]: 2.5

np.average(a,weights=w)
Out[334]: 2.1000000000000001
複製代碼

5. 字符串函數

函數 做用 說明
np.char.add 字符串相加 逐個元素執行字符串相加
np.char.multiply 字符串重複 第二個參數i爲重複次數
np.char.center 字符串居中 第二個參數width爲長度,第三個參數fillchar爲填充字符
np.char.capitalize 首字母大寫 -
np.char.title 單詞首字母大寫 -
np.char.lower 轉換爲小寫 -
np.char.upper 轉換爲大寫 -
np.char.split 字符串分割 第二個參數sep爲分隔符,返回list數組
np.char.splitlines 行分割 以換行符分割,返回list數組
np.char.strip 移除頭尾指定字符 第二個參數chars爲須要移除的字符
np.char.join 以指定分隔符拼接字符 第一個參數sep爲分隔符
np.char.replace 替換字符串 第二個參數old爲舊字符串,第三個參數new爲新字符串
np.char.decode 解碼 對每一個元素調用str.decode
np.char.encode 編碼 對每一個元素調用str.encode

(如下是部分示例)

np.char.add

a1=np.array(['a','b']);a2=np.array(['c','d'])

np.char.add(a1,a2)
Out[302]: 
array(['ac', 'bd'],
      dtype='<U2')
複製代碼

np.char.multiply

a=np.array(['a','b'])

np.char.multiply(a,3)
Out[304]: 
array(['aaa', 'bbb'],
      dtype='<U3')
複製代碼

np.char.center

a=np.array(['a','b'])

np.char.center(a,10,'*')
Out[306]: 
array(['****a*****', '****b*****'],
      dtype='<U10')
複製代碼

np.char.split

a=np.array(['a,b','c,d'])

np.char.split(a,',')
Out[308]: array([list(['a', 'b']), list(['c', 'd'])], dtype=object)
複製代碼

np.char.join

a=np.array(['ab','cd'])

np.char.join(',',a)
Out[310]: 
array(['a,b', 'c,d'],
      dtype='<U3')

a=np.array(['a,b','c,d'])

np.char.join(',',np.char.split(a,','))
Out[312]: 
array(['a,b', 'c,d'],
      dtype='<U3')
複製代碼

注意,該方法沒法實現多維數組的聚合計算。在數組元素爲字符串時,會對字符串中的每一個元素進行拼接;在數組元素爲字符串序列時,會對序列中的字符串進行拼接。 與split互爲逆運算。

6. 線性代數運算

函數 做用 說明
np.dot(a1,a2) 點乘 多維數組下會將a1的最後一個軸和a2的倒數第二個軸做爲向量的維度,可視做向量的棧
np.vdot(a1,a2) 向量點乘 高維數組會被展開計算
np.inner(a1,a2) 向量內積 多維數組會將最後一個軸做爲向量的維度
np.matmul(a1,a2) 矩陣乘積 多維數組下會將最後兩個軸做爲矩陣的維度,可視做元素是矩陣的數組
np.linalg.det(a) 行列式 行列式描述的是矩陣所表示的線性變換對「體積」的影響
np.linalg.solve(A,b) 求解線性方程組 求解線性方程組Ax = b,A爲係數矩陣(方陣),b爲常數矩陣
np.linalg.lstsq(A,b) 求解線性方程組 求線性方程組Ax = b的最小二乘解,A爲係數矩陣,b爲常數矩陣
np.linalg.inv(a) 逆矩陣 AB=BA=E,E爲單位矩陣,則B爲A的逆矩陣
np.linalg.pinv(a) 廣義逆矩陣 能夠輸入非方陣
np.linalg.eig(a) 特徵值和特徵向量 返回兩個數組
np.linalg.qr(a) 正交分解 -
np.linalg.svd(a) 奇異值分解 -
ndarray.T 轉置 對一維數組轉置是無效的

(如下是部分示例)

np.dot, np.vdot, np.inner, np.matmul

a=np.array([1,2]);b=np.array([[3,4],[5,6]])

np.dot(a,a), np.vdot(a,a), np.inner(a,a), np.matmul(a,a)
Out[340]: (5, 5, 5, 5)

np.dot(a,b), np.dot(b,a)
Out[341]: (array([13, 16]), array([11, 17]))

np.vdot(a,b)
Traceback (most recent call last):

  File "<ipython-input-358-f2388a21d848>", line 1, in <module>
    np.vdot(a,b)

ValueError: cannot reshape array of size 4 into shape (2,)

np.inner(a,b), np.inner(b,a)
Out[343]: (array([11, 17]), array([11, 17]))

np.matmul(a,b), np.matmul(b,a)
Out[344]: (array([13, 16]), array([11, 17]))

np.dot(b,b)
Out[345]: 
array([[29, 36],
       [45, 56]])

np.vdot(b,b)
Out[346]: 86

np.inner(b,b)
Out[347]: 
array([[25, 39],
       [39, 61]])

np.matmul(b,b)
Out[348]: 
array([[29, 36],
       [45, 56]])
複製代碼

這四個方法執行的運算都基於向量內積,很是類似,但在具體行爲上有區別,很容易混淆。

dot是將數組看做向量的集合,第一個數組的最後一個軸和第二個數組的倒數第二個軸做爲向量的軸,抽取每一個向量兩兩匹配進行點積運算,所以這兩個軸須要長度一致。例如,a.shape=(2,3,4)b.shape=(5,4,6),則np.dot(a,b).shape=(2,3,5,6)。在二維狀況下,實現的計算便是矩陣乘法。

vdot的規則比較簡單,會將數組展開爲向量再計算點積,要求數組的size一致。

innerdot相似,但規則更簡單,兩個數組均以最後一個軸做爲向量的軸,即最後一個軸長度要保持一致。例如,a.shape=(2,3,4)b.shape=(5,6,4),則np.dot(a,b).shape=(2,3,5,6)

matmul的計算針對矩陣,和dot同樣在二維狀況下表示矩陣乘法,二維以上視做元素爲矩陣的數組,參與運算的兩個數組均以最後兩個軸做爲矩陣的軸,逐個元素進行矩陣乘法並向其餘軸方向上廣播。例如,a.shape=(1,3,4)b.shape=(5,4,6),則np.dot(a,b).shape=(5,3,6),若是a.shape=(2,3,4),計算就會報錯,由於不知足廣播的規則。

7. 集合運算

函數 做用 說明
np.intersect1d(x, y) 交集 xy的公共元素
np.union1d(x, y) 並集 xy的全部元素
np.setdiff1d(x, y) 集合差 x中存在,y中不存在的元素
np.setxor1d(x, y) 集合異或 xy的獨佔元素

以上方法適用於一維數組。

(如下是部分示例)

x=np.array([1,3,4])
y=np.array([2,3,5])

np.intersect1d(x,y)
Out[812]: array([3])

np.union1d(x,y)
Out[813]: array([1, 2, 3, 4, 5])

np.setdiff1d(x,y)
Out[814]: array([1, 4])

np.setxor1d(x,y)
Out[815]: array([1, 2, 4, 5])
複製代碼

8. 位運算

函數 做用 說明
np.invert 按位取反 等效於~運算符
np.bitwise_and 按位與 等效於&運算符
np.bitwise_or 按位或 等效於\|運算符
np.bitwise_xor 按位異或 等效於^運算符
np.left_shift 位左移 等效於<<運算符
np.right_shift 位右移 等效於>>運算符

(如下是部分示例)

a=np.array([2,3,5,8,13])
b=np.array([3,4,7,11,18])

np.invert(a)
Out[860]: array([ -3,  -4,  -6,  -9, -14], dtype=int32)

bin(a[4]),bin(~a[4])
Out[862]: ('0b1101', '-0b1110')

np.bitwise_and(a,b)
Out[863]: array([2, 0, 5, 8, 0], dtype=int32)

bin(a[3]),bin(b[3]),bin(a[3]&b[3])
Out[865]: ('0b1000', '0b1011', '0b1000')
複製代碼

np.invert對於有符號整數,取對應二進制數的補碼,而後 +1。二進制數形式的最高位爲0表示正數,最高位爲 1 表示負數。

9. 廣播

numpy在進行不一樣形狀的數組之間的計算時,會自動沿長度不足且長度爲1的軸方向進行廣播。當維數不一致時,會向前補齊,這要求後面的軸長度相同或是有一方長度等於1,即從後至前進行軸長比對,例如形狀(a,b,c)與(b,c)可計算,(a,b,c)與(b,1)可計算,(a,b,c)與(a,b,1)可計算,(a,b,c)與(a,b)不可計算,(a,b,c)與(a,c,b)不可計算。

a1=np.zeros((2,3,4))
a2=np.random.randint(0,10,(3,4))
a3=np.random.randint(0,10,(2,3))
a4=np.random.randint(0,10,(2,3,1))

a1+a2
Out[418]: 
array([[[ 3.,  6.,  0.,  6.],
        [ 9.,  6.,  3.,  4.],
        [ 2.,  3.,  1.,  5.]],

       [[ 3.,  6.,  0.,  6.],
        [ 9.,  6.,  3.,  4.],
        [ 2.,  3.,  1.,  5.]]])

a1+a3
Traceback (most recent call last):

  File "<ipython-input-419-d778f9717621>", line 1, in <module>
    a1+a3

ValueError: operands could not be broadcast together with shapes (2,3,4) (2,3) 

a1+a4
Out[420]: 
array([[[ 0.,  0.,  0.,  0.],
        [ 9.,  9.,  9.,  9.],
        [ 1.,  1.,  1.,  1.]],

       [[ 4.,  4.,  4.,  4.],
        [ 0.,  0.,  0.,  0.],
        [ 2.,  2.,  2.,  2.]]])
複製代碼

10. 常量

屬性名 常量名
np.e 天然指數 2.718281828459045
np.pi 圓周率 3.141592653589793
np.euler_gamma 歐拉常數 0.5772156649015329
np.inf 無窮大 -
np.nan 非數值 -

四. 查找

返回目錄

1. 索引

經過ndarray[index1,index2...]的形式指定索引。

(1). 定位元素

a=np.array([[1,2],[3,4]])

a[1,1]
Out[453]: 4
複製代碼

(2). 數據切片

a[:,1]
Out[454]: array([2, 4])

a[0:1,:]
Out[455]: array([[1, 2]])
複製代碼

經過low:high的形式限定索引範圍,區間前閉後開,上下限留空表示不限制。 標量值索引會使對應維度消失,範圍索引則不會。

(3). 倒序索引

a[-1,:-1]
Out[457]: array([3])
複製代碼

-n表示倒數第n個。

(4). 按步長選取

a[0:2:2]
Out[458]: array([[1, 2]])
複製代碼

經過low:high:step的形式限定索引範圍和步長。

(5). 序列反轉

a[::-1]
Out[459]: 
array([[3, 4],
       [1, 2]])
複製代碼

等效於a[-1:-len(a)-1:-1]

(6). 布爾索引

a>2
Out[460]: 
array([[False, False],
       [ True,  True]], dtype=bool)

(a>2)&(a<4)
Out[461]: 
array([[False, False],
       [ True, False]], dtype=bool)

a[(a>2)&(a<4)]
Out[462]: array([3])
複製代碼

ndarray應用邏輯運算符會獲得布爾索引,布爾索引標識了每一個元素符合邏輯判斷條件的狀況,使用該索引篩選數組將獲得全部知足條件的元素構成的一維數組。

(7). 數組索引

a[[0,1],[1]]
Out[463]: array([2, 4])

a[[0,1],[1,0]]
Out[464]: array([2, 3])
複製代碼

將對應軸上須要選取的索引以數組形式傳入,當在多個軸上傳入數組索引時,索引會被一一對應。支持list,tuple,ndarray,支持倒序索引。

(8). 綜合示例

獲取第二列大於2的行的第一列
a[a[:,1]>2,0]
Out[465]: array([3])
複製代碼
獲取二維數組的頂角元素
a[[0,-1]][:,[0,-1]]
Out[466]: 
array([[1, 2],
       [3, 4]])

a[[0,0,-1,-1],[0,-1,0,-1]].reshape((2,2))
Out[467]: 
array([[1, 2],
       [3, 4]])
複製代碼

此處使用的reshape重塑方法會在重構章節講到。

(9). 獲取布爾索引指示的位置

a>2
Out[473]: 
array([[False, False],
       [ True,  True]], dtype=bool)

np.where(a>2)
Out[474]: (array([1, 1], dtype=int64), array([0, 1], dtype=int64))

a[np.where(a>2)]
Out[476]: array([3, 4])

np.where(a>2,a,-a)
Out[477]: 
array([[-1, -2],
       [ 3,  4]])
複製代碼

只輸入數組時,內部會調用nonzero方法,返回值爲一個tuple,包含每一個軸上的索引值序列。 經過第二個參數x和第三個參數y,能夠根據是否知足條件對元素進行不一樣的計算,返回一樣形狀的數組。

(10). 特定值查找

指定值序列
a=np.arange(5)

np.isin(a,[3,4])
Out[656]: array([False, False, False,  True,  True], dtype=bool)
複製代碼

第二個參數test_elements爲指定值序列,返回布爾索引。

值排序搜索
a=np.array([1,3,5,7,9])

np.searchsorted(a,[3,6])
Out[684]: array([1, 3], dtype=int64)
複製代碼

第一個參數a爲升序一維數組,非升序可經過第四個參數指定排序sorter=np.argsort(a),第二個參數v爲須要被插入a的值或值序列,第三個參數side爲判斷方式,'left'表示a[i-1] < v <= a[i]'right'表示a[i-1] <= v < a[i]。該方法將逐個搜索v的每一個元素在升序數組a中合適的插入位置,返回數組索引。

空值
a=np.array([np.nan,1,2,3])

np.isnan(a)
Out[662]: array([ True, False, False, False], dtype=bool)
複製代碼

返回布爾索引。

(11). 返回索引的方法

函數 做用 說明
np.argsort 返回排序後索引 -
np.argmax 返回最大值索引 -
np.argmin 返回最小值索引 -
np.argpartition 返回分區索引 第二個參數kth指定用於分區的元素索引
np.argwhere 返回符合條件的值索引 np.where相似,但返回值的形式不太適合索引
np.where 返回符合條件的值索引 -
np.isin 返回判斷元素是否在指定列表中的布爾索引 第二個參數test_elements爲指定的值序列
np.isnan 返回判斷元素是否nan值的布爾索引 -
np.searchsorted 返回待插入值在升序序列中的插入位置 第一個參數a爲升序一維數組,第二個參數v爲待插入值
np.digitize 返回分箱後的索引 第二個參數bins指定分箱方式

2. 遍歷

(1). 序列結構遍歷

a=np.array([[1,2],[3,4]])

for buf1 in a:
    for buf2 in buf1:
        print(buf2)
複製代碼

(2). 索引遍歷

for i in range(a.shape[0]):
    for j in range(a.shape[1]):
        print(a[i,j])
複製代碼

以上兩種方法在遍歷元素時,維數是多少就要嵌套多少層循環,效率不算高,但能夠在每一層循環中嵌入額外的計算。

(3). 快速迭代器遍歷

for item in np.nditer(a):
    print(item)
複製代碼

默認選擇元素的順序是和數組內存佈局一致的,而不是使用標準C或者Fortran順序。這是爲了使用效率而設計的,這反映了默認狀況下只需訪問每一個元素,而無需考慮其特定順序。可經過order參數來指定特定的順序來訪問數組。

(4). 平鋪迭代器遍歷

for item in a.flat:
    print(item)
複製代碼

將數組轉換爲1-D的迭代器。

3. 抽樣

(1). 無放回抽樣

a=np.array([[1,2],[3,4]])
idx=np.random.choice(np.arange(a.shape[0]),size=1,replace=False)

a[idx]
Out[508]: array([[3, 4]])
複製代碼

(2). 有放回抽樣

idx=np.random.randint(0,a.shape[0],size=3)

a[idx]
Out[512]: 
array([[1, 2],
       [3, 4],
       [1, 2]])
複製代碼

也可以使用np.random.choice(np.arange(a.shape[0]),size=3)生成索引。 以上都是在單個軸方向上抽樣,若是想在多個軸方向上抽樣,因爲抽樣後必然會破壞數組結構,建議先將用於抽樣的軸展開,好比用reshape方法,見下面的示例,關於reshape方法的說明在重構章節。

(3). 多軸方向抽樣

a=np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
a2=a.reshape((2,4))
idx=np.random.randint(0,a2.shape[0],size=2)

a2[:,idx]
Out[527]: 
array([[1, 2],
       [5, 6]])
複製代碼

4. 視圖

在對數組進行了索引切片後,返回的一般是原數組的一個視圖,不會完整的拷貝數據,所以在這種狀況下進行更新操做會影響到原數組和全部視圖。 可經過ndarray.view()方法得到一個完整視圖,等效於ndarray[:,:,...]。 想將視圖轉換爲拷貝可以使用ndarray.copy()方法。

a=np.array([[1,2],[3,4]])
a2=a[1,:]

a2
Out[544]: array([3, 4])

a2[:]=0

a
Out[546]: 
array([[1, 2],
       [0, 0]])
複製代碼

五. 變動

返回目錄

1. 更新

(1). 更新整個數組

a=np.array([[1,2],[3,4]])

a=a+1

a
Out[557]: 
array([[2, 3],
       [4, 5]])

a[:,:]=a-1

a
Out[559]: 
array([[1, 2],
       [3, 4]])
複製代碼

兩種方式都能更新整個數組,第一種將計算獲得的新數組的引用從新賦給了a,第二種根據計算獲得的新數組更新了原數組中相應位置的值。

(2). 更新指定位置

a[a>2]+=1

a
Out[570]: 
array([[1, 2],
       [4, 5]])

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

a
Out[572]: 
array([[1, 2],
       [5, 6]])

a[0,:]=0

a
Out[574]: 
array([[0, 0],
       [5, 6]])

a[a>2]=[3,4]

a
Out[576]: 
array([[0, 0],
       [3, 4]])
複製代碼

值數組形狀須要與篩選後的原數組一致或遵循廣播的規則。

(3). 定值填充

a.fill(1)

a
Out[10]: 
array([[1, 1],
       [1, 1]])
複製代碼

當填充值數據類型與數組數據類型不一致時,會嘗試轉換,失敗時纔會報錯。

2. 擴增

(1). 插入

a=np.array([[1,2],[3,4]])

np.insert(a,1,[5,6],axis=0)
Out[578]: 
array([[1, 2],
       [5, 6],
       [3, 4]])
複製代碼

第二個參數obj是插入的位置索引,第三個參數values是待插入的值,須要與指定軸方向上的切片形狀一致或知足廣播規則,第四個參數axis是指定的軸。不影響原數組,返回的是一個拷貝。

(2). 附加

np.append(a,[[5,6]],axis=0)
Out[578]: 
array([[1, 2],
       [3, 4],
       [5, 6]])
複製代碼

第二個參數values是待插入的值,須要與指定軸方向上的切片形狀一致或知足廣播規則,第三個參數axis是指定的軸。只能將新數據附加到數組末尾。不影響原數組,返回的是一個拷貝。

(3). 堆疊

np.c_[a,a]
Out[589]: 
array([[1, 2, 1, 2],
       [3, 4, 3, 4]])

np.column_stack((a,a))
Out[590]: 
array([[1, 2, 1, 2],
       [3, 4, 3, 4]])

np.concatenate((a,a),axis=1)
Out[591]: 
array([[1, 2, 1, 2],
       [3, 4, 3, 4]])

np.r_[a,a]
Out[592]: 
array([[1, 2],
       [3, 4],
       [1, 2],
       [3, 4]])

np.row_stack((a,a))
Out[593]: 
array([[1, 2],
       [3, 4],
       [1, 2],
       [3, 4]])

np.concatenate((a,a),axis=0)
Out[594]: 
array([[1, 2],
       [3, 4],
       [1, 2],
       [3, 4]])

np.stack((a,a),axis=0)
Out[595]: 
array([[[1, 2],
        [3, 4]],

       [[1, 2],
        [3, 4]]])
複製代碼

np.c_np.column_stack是沿軸1進行堆疊,其餘軸長度須要相同或知足廣播規則,等效於np.concatenate(axis=1)np.r_np.row_stack是沿軸0進行堆疊,其餘軸長度須要相同或知足廣播規則,等效於np.concatenate(axis=0)np.stack是沿新軸進行堆疊,全部軸長度須要相同或知足廣播規則。

(4). 重複

a.repeat(3,axis=1)
Out[93]: 
array([[1, 1, 1, 2, 2, 2],
       [3, 3, 3, 4, 4, 4]])

a.reshape((2,2,1)).repeat(3,axis=2)
Out[96]: 
array([[[1, 1, 1],
        [2, 2, 2]],

       [[3, 3, 3],
        [4, 4, 4]]])

a.repeat(3).reshape((2,2,3))
Out[98]: 
array([[[1, 1, 1],
        [2, 2, 2]],

       [[3, 3, 3],
        [4, 4, 4]]])

np.tile(a,2)
Out[99]: 
array([[1, 2, 1, 2],
       [3, 4, 3, 4]])

np.tile(a,[2,2])
Out[100]: 
array([[1, 2, 1, 2],
       [3, 4, 3, 4],
       [1, 2, 1, 2],
       [3, 4, 3, 4]])

np.tile(a.ravel(),2)
Out[101]: array([1, 2, 3, 4, 1, 2, 3, 4])
複製代碼

repeat方法將數組中的元素重複,可經過axis參數指定軸方向,默認會將數組展開後在惟一的軸方向上重複元素。可配合ndarray.reshape在新軸上覆制元素。 tile方法將數組重複,注意,重複的是整個數組,不是單個元素,獲得的結果中同元素不必定是緊挨着的。

3. 刪除

(1). 索引篩選

a[~(a[0]==1),:]
Out[616]: array([[3, 4]])
複製代碼

經過索引篩選可獲得刪除指定內容的數組。

(2). 刪除方法

np.delete(a,[0,1],axis=0)
Out[617]: array([], shape=(0, 2), dtype=int32)
複製代碼

經過相應方法得到刪除指定索引位置內容的數組。第二個參數obj爲索引位置,第三個參數axis爲指定軸。

六. 重構

返回目錄

1. 類型轉換

a=np.array([[1,2],[3,4]])

a.dtype
Out[620]: dtype('int32')

a=a.astype('float64')

a.dtype
Out[622]: dtype('float64')

a=np.int32(a)

a.dtype
Out[624]: dtype('int32')
複製代碼

使用ndarray.astype方法或是使用數據類型同名方法均可以轉換類型,關於numpy支持的數據類型能夠查看屬性章節。轉換類型後返回一個新數組。

2. 重塑

(1). 改變形狀

a=np.array([[1,2],[3,4]])

a.reshape((1,4))
Out[626]: array([[1, 2, 3, 4]])

a.reshape((-1,4))
Out[627]: array([[1, 2, 3, 4]])
複製代碼

使用tuple類型的參數聲明新的形狀。容許有一個新軸的大小爲-1,表示自動計算。 改變先後元素數size須要保持一致。元素在軸上的排列是從最後一個軸開始往前面的軸方向上堆疊,見以下圖示,可經過order參數指定其餘排序方式。軸的相對位置不會改變,因此一些複雜的變形可能須要結合transposeswapaxes此類軸交換方法使用。

(2). 平鋪

a.ravel()
Out[640]: array([1, 2, 3, 4])

a.flatten()
Out[641]: array([1, 2, 3, 4])
複製代碼

將數組平鋪爲向量,等效於reshape((-1,)),可經過order參數指定其餘排序方式。

(3). 轉置

a.T
Out[643]: 
array([[1, 3],
       [2, 4]])
複製代碼

數組爲一維時轉置無效,爲二維時即矩陣的轉置,多於二維時交換第一個和最後一個軸。

(4). 軸交換

a.swapaxes(0,1)
Out[646]: 
array([[1, 3],
       [2, 4]])

a.transpose([1,0])
Out[647]: 
array([[1, 3],
       [2, 4]])
複製代碼

swapaxes一次只能指定兩個軸進行交換,transpose能夠從新爲全部軸排序。

3. 排序

(1). 直接排序

a=np.array([[2,3],[1,4]])

np.sort(a,axis=None)
Out[735]: array([1, 2, 3, 4])

a.sort(axis=0)

a
Out[737]: 
array([[1, 3],
       [2, 4]])
複製代碼

ndarray.sort會直接在原數組上排序,可經過第一個參數axis指定排序的軸,會將沿着該軸方向的每一個向量單獨排序,默認-1,除沿最後一個軸外,指定其餘軸都會在排序時生成數據的臨時副本,所以沿最後一個軸排序最快。 等效方法np.sort,返回的是排序後的副本,還可指定axis=None,會將數組展開再排序。 當數組的維度具有實際含義時,直接排序會打亂數據結構,獲得不被指望的結果,這種狀況下須要使用間接排序。

(2). 間接排序

a=np.array([[2,3,5],[1,1,4],[1,2,3]])

a
Out[741]: 
array([[2, 3, 5],
       [1, 1, 4],
       [1, 2, 3]])

idx1=np.argsort(a[:,0])

a[idx1]
Out[743]: 
array([[1, 1, 4],
       [1, 2, 3],
       [2, 3, 5]])

idx2=np.lexsort((a[:,0],a[:,2]))

a[idx2]
Out[745]: 
array([[1, 2, 3],
       [1, 1, 4],
       [2, 3, 5]])
複製代碼

argsort可用於單鍵間接排序,lexsort可用於多鍵間接排序。

(3). 隨機排序

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

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

np.random.shuffle(a)

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

idx=np.random.permutation(a.shape[1])

a[:,idx]
Out[769]: 
array([[ 4,  5,  7,  6],
       [ 0,  1,  3,  2],
       [ 8,  9, 11, 10]])
複製代碼

方法一np.random.shuffle只能沿第一個軸進行隨機排序,方法二是經過np.random.permutation,該方法也只能沿第一個軸隨機排序,但在輸入參數xint類型時,會對np.arange(x)進行隨機排序,能夠快速生成亂序索引,再經過索引查找獲得亂序數組。

(4). 分區排序

a=np.array([2,3,1,5,4,0,8])

np.partition(a,1)
Out[800]: array([0, 1, 3, 5, 4, 2, 8])

np.partition(a,4)
Out[801]: array([0, 1, 2, 3, 4, 5, 8])
複製代碼

分區排序是一種不完整的排序,用於不須要獲取完整排序序列的狀況下。該方法只保證kth指定位置的元素是正確排序的,其餘小於該元素的元素前移,大於的後移。可用於快速找出第k大或第k小的元素。 也可經過ndarray.partition調用,axis參數指定軸方向,還有對應的np.argpartition用於獲取分區後的索引。

4. 去重

a=np.array([3,2,2,3,1,1,4])

np.unique(a,return_index=True,return_inverse=True,return_counts=True,axis=None)
Out[776]: 
(array([1, 2, 3, 4]),
 array([4, 1, 0, 6], dtype=int64),
 array([2, 1, 1, 2, 0, 0, 3], dtype=int64),
 array([2, 2, 2, 1], dtype=int64))

a=np.array([[1,3],[2,4],[1,3]])

np.unique(a,axis=0)
Out[778]: 
array([[1, 3],
       [2, 4]])
複製代碼

axis指定去重的軸,默認None會將數組展開後再去重。 返回值一爲去重後的有序值列表; 返回值二爲惟一值在原數組中的索引,僅在return_index=True時提供; 返回值三爲根據惟一值重建原數組的索引,僅在return_inverse=True時提供; 返回值四爲惟一值的出現計數,僅在return_counts=True時提供。

5. 拆分

(1). 索引拆分

a=np.arange(9).reshape((3,3))

a[:2,:],a[2:,:]
Out[781]: 
(array([[0, 1, 2],
        [3, 4, 5]]), array([[6, 7, 8]]))

a[a>2],a[~(a>2)]
Out[782]: (array([3, 4, 5, 6, 7, 8]), array([0, 1, 2]))

idx=np.random.permutation(a.shape[0])
sp_idx=int(a.shape[0]*0.8)

a[idx[:sp_idx]],a[idx[sp_idx:]]
Out[792]: 
(array([[3, 4, 5],
        [6, 7, 8]]), array([[0, 1, 2]]))
複製代碼

最靈活的方式,複雜的拆分須要寫較多的代碼,可以使用其餘方法配合生成用於拆分的索引,好比使用np.digitize進行分箱。

(2). 拆分方法

a=np.arange(8)

np.split(a,2)
Out[803]: [array([0, 1, 2, 3]), array([4, 5, 6, 7])]

np.split(a,[2,5])
Out[805]: [array([0, 1]), array([2, 3, 4]), array([5, 6, 7])]

a=a.reshape((2,4))

a
Out[807]: 
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

np.split(a,[1,3],axis=1)
Out[809]: 
[array([[0],
        [4]]), array([[1, 2],
        [5, 6]]), array([[3],
        [7]])]
複製代碼

第二個參數indices_or_sections指定分割方式,int類型表示等分數量,一維數組類型表示用於分割的索引值,例如[2,5]表示分割爲a[:2],a[2:5],a[5:]。 第三個參數axis能夠指定軸方向。

七. 讀寫

返回目錄

numpy 可以使用專用的npynpz格式或常見的txt格式存儲ndarray的數據。

1. 保存

a=np.array([1,2,3,4])
b=np.array([[5,6],[7,8]])

np.save('D:\\out.npy',a)

np.savez('D:\\out.npz',a,b=b)

np.savetxt('D:\\out.txt',b,fmt="%d", delimiter=",")
複製代碼

拓展名能夠省略,會自動補全。沒法自動建立文件夾。 save用於保存單個數組爲npy格式文件。 savez用於保存多個數組爲npz格式文件,沒有使用關鍵字參數傳遞的數組會自動命名爲arr_0,arr_1,...savetxt用於保存單個數組爲txt格式文件,參數fmt指定保存時的字符串轉換,參數delimiter指定分隔符,注意在讀取時也須要指定分隔符。分隔符的設置對一維數組無效,二維以上的數組不適合用該方法保存。

2. 加載

np.load('D:\\out.npy')
Out[835]: array([1, 2, 3, 4])

npz=np.load('D:\\out.npz')

npz['arr_0']
Out[837]: array([1, 2, 3, 4])

npz['b']
Out[838]: 
array([[5, 6],
       [7, 8]])

np.loadtxt('D:\\out.txt',dtype='int',delimiter=',')
Out[841]: 
array([[5, 6],
       [7, 8]])
複製代碼

np.load讀取npz格式文件會獲得一個NpzFile對象,以後經過保存時設置的名稱進行[]索引能夠取得每個數組。

八. 其餘

返回目錄

1. 矩陣類型

numpy提供了一個專用的矩陣對象matrix,是基於 ndarray做了進一步的封裝獲得的,可以更加快捷地進行一些矩陣相關的運算,但相比ndarray沒有性能上的優點且維數限制在二維,並不推薦使用。

(1). 建立

m1=np.matrix([[1,2],[3,4]])

m1
Out[81]: 
matrix([[1, 2],
        [3, 4]])
複製代碼

建立方式與ndarray相似。

(2). 與 ndarray的相互轉換

a=np.array([[5,6],[7,8]])
m2=np.matrix([[5,6],[7,8]])

np.asmatrix(a)
Out[84]: 
matrix([[5, 6],
        [7, 8]])

np.matrix(a)
Out[85]: 
matrix([[5, 6],
        [7, 8]])

np.asarray(m2)
Out[88]: 
array([[5, 6],
       [7, 8]])

np.array(m2)
Out[89]: 
array([[5, 6],
       [7, 8]])

m2.base
Out[90]: 
array([[5, 6],
       [7, 8]])
複製代碼

(3). 矩陣運算

m1*m2
Out[94]: 
matrix([[19, 22],
        [43, 50]])

m1.I
Out[95]: 
matrix([[-2. ,  1. ],
        [ 1.5, -0.5]])

m1.T
Out[96]: 
matrix([[1, 3],
        [2, 4]])
複製代碼

運算符*用在matrix上表示矩陣乘法,等效於np.dot(m1,m2),要實現元素相乘須要使用np.multiply(m1,m2)matrix.T表示轉置矩陣,matrix.I表示逆矩陣。 matrix可使用大部分ndarray的方法,好比maxsumsort等。

2. 張量運算

張量是向量、矩陣這類概念的推廣,標量是0階張量,向量是1階張量,矩陣是2階張量。 numpy提供了廣義的張量點積運算np.tensordot

a=np.arange(1,9).reshape((2,2,2))
b=np.arange(1,5).reshape((2,2))

a
Out[4]: 
array([[[1, 2],
        [3, 4]],

       [[5, 6],
        [7, 8]]])

b
Out[5]: 
array([[1, 2],
       [3, 4]])

np.tensordot(a,b,axes=1)
Out[8]: 
array([[[ 7, 10],
        [15, 22]],

       [[23, 34],
        [31, 46]]])

np.tensordot(a,b,axes=(-1,0))
Out[9]: 
array([[[ 7, 10],
        [15, 22]],

       [[23, 34],
        [31, 46]]])

np.tensordot(a,b,axes=2)
Out[10]: array([30, 70])

np.tensordot(a,b,axes=([-2,-1],[0,1]))
Out[12]: array([30, 70])

np.dot(a,b)
Out[13]: 
array([[[ 7, 10],
        [15, 22]],

       [[23, 34],
        [31, 46]]])

np.tensordot(a,b,axes=(-1,-2))
Out[14]: 
array([[[ 7, 10],
        [15, 22]],

       [[23, 34],
        [31, 46]]])

np.inner(a,b)
Out[15]: 
array([[[ 5, 11],
        [11, 25]],

       [[17, 39],
        [23, 53]]])

np.tensordot(a,b,axes=(-1,-1))
Out[16]: 
array([[[ 5, 11],
        [11, 25]],

       [[17, 39],
        [23, 53]]])
複製代碼

前兩個參數ab爲參與運算的兩個張量。 第三個參數axes用於指定收縮的軸,完整格式形如([a_axis1,a_axis2,...],[b_axis1,b_axis2,...]),兩個序列分別指定ab的軸,軸方向上的元素會按照被指定的順序對應、相乘並相加;可以使用(a_axis,b_axis)的形式僅指定一個軸; 可以使用int類型快速指定a中最後N個軸和b中前N個軸用於收縮,即0等效於([],[]),對應張量積運算,1等效於([-1],[0]),對應張量內積運算,2等效於([-2,-1],[0,1]),對應張量雙收縮運算,axes的默認值爲2np.dotnp.inner這類運算可視做該函數表示的幾個特例,np.dot(a1,a2)等效於np.tensordot(a1,a2,axes=(-1,-2))np.inner(a1,a2)等效於np.tensordot(a1,a2,axes=(-1,-1))

3. 傅里葉變換

(1) 頻率序列

np.fft.fftfreq(10,1.0)
Out[12]: array([ 0. ,  0.1,  0.2,  0.3,  0.4, -0.5, -0.4, -0.3, -0.2, -0.1])
複製代碼

返回離散傅里葉變換採樣頻率,第一個參數n爲窗口長度,int類型,第二個參數d爲採樣間距(採樣率的倒數),默認爲1.0,返回值單位與採樣間距單位相對應。 返回值序列的計算方式: 若是n是偶數,f = [0, 1, ..., n/2-1, -n/2, ..., -1] / (d*n); 若是n是奇數,f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n)

(2) 快速傅里葉變換

x=np.cos(np.linspace(0,2*np.pi,30))
y=np.fft.fft(x)
x2=np.fft.ifft(y)

np.abs(x2-x).max()
Out[16]: 3.8864883384594504e-16
複製代碼

np.fftnp.ifft互爲逆運算,用於一維快速傅里葉變換,經np.fft變換後的序列可經過np.ifft近似還原爲原序列。 第二個參數n指定輸出的變換軸長度,超長裁剪,不足補0; 第三個參數axis指定用於變換的軸,默認最後一個軸。

(3) 移頻

x=np.linspace(0,2*np.pi,8)
y=np.fft.fft(x)
y2=np.fft.fftshift(y)
y3=np.fft.ifftshift(y2)

np.abs(y3-y).max()
Out[32]: 0.0
複製代碼

np.fftshiftnp.ifftshift互爲逆運算,用於將傅里葉變換輸出中的直流份量移動到頻譜的中央。第二個參數axis可指定用於轉移的軸。

4. 圖像處理

圖像數據的存儲方式是相似於數組的,可藉助PIL庫讀取圖片,再將圖像數據轉成ndarray進行計算處理。 如下提供一些使用numpy配合PIL處理圖片數據的方法:

(1) 圖片的建立、讀取、縮放、保存

from PIL import Image
image1= Image.open("D:\\test.jpg")

image1.size
Out[3]: (1015, 610)

image2=image1.resize((500,300))
image2.save("D:\\test2.jpg")
image0=Image.new('RGB',image2.size)

image2
Out[7]: 
複製代碼

Image.open用於打開一張圖片,mode能夠設置讀取模式,最經常使用的是'L'灰度圖和'RGB'彩色圖,通常會自動匹配不須要設置。 圖片對象的resize方法能夠縮放圖片,大小參數以tuple類型(width,height)格式傳入。 圖片對象的save方法能夠保存圖片,經過保存路徑中的文件拓展名或是format參數指定保存文件類型,quality參數能夠設置保存圖像的質量,取值1(最差)~ 95(最佳),默認75。 Image.new用於建立一個新的圖片,mode參數指定模式,size指定大小。 在IPython中,直接輸入圖片變量名就能夠顯示圖片。

(2) 圖片與數組之間的轉換

a=np.asarray(image2)

a.shape
Out[8]: (300, 500, 3)

image3=Image.fromarray(a,'RGB')
複製代碼

np.asarraynp.array能夠將圖片轉換爲ndarraynp.asarray返回圖片數據的ndarray類型視圖,不能更改。根據類型的不一樣,獲得的數組形狀也不同,常見的兩種,灰度圖轉換獲得形狀爲(height,width)的數組,彩色圖轉換獲得形狀爲(height,width,channel)的數組,channel即顏色通道,RGB模式下channel=3,分別對應紅綠藍。 Image.fromarray能夠將ndarray轉換爲圖片,可經過mode參數指定模式,默認會根據數組形狀自動匹配,當指定某個模式時,數組形狀也須要匹配。 注意,數組轉圖片須要是uint8數據類型,取值0~255,如不符合要進行另外的轉換。

(3) 像素點繪製

a0=np.array(image0)
a0+=np.random.randint(0,256,a.shape,dtype='uint8')
image4=Image.fromarray(a0)
image4.putpixel((0,0),(255,255,255))

image4 
Out[14]: 
複製代碼

圖片對象的putpixel方法能夠添加單個像素點,第一個參數xy(x,y)的形式聲明添加像素點的位置,第二個參數value指定像素點的值,例如,L灰度圖模式下爲標量值,RGB彩色圖模式下爲(r,g,b)形式的tuple,取值均在0~255之間。該方法一次只能繪製一個像素點,效率低,在須要批量繪製時建議轉換爲ndarray處理。 上面的示例中使用ndarray的方法爲新圖片的每個像素點添加了隨機色彩。

(4) 灰度圖和彩色圖之間的轉換

a2=np.asarray(image2,dtype='float')

a5=(11*a2[:,:,0]+16*a2[:,:,1]+5*a2[:,:,2])/32
image5=Image.fromarray(np.uint8(a5))

a6=a5.repeat(3).reshape(a5.shape+(3,))
image6=Image.fromarray(np.uint8(a6))

image5
Out[77]: 
複製代碼

彩色圖轉灰度圖, L=11*R+16*G+5*B只是一種可行的公式,也有其餘公式可用。 灰度圖轉彩色圖,較爲簡單,即將灰度值拷貝到 RGB3個通道上,轉換後顏色仍是灰色,由於灰度圖不具有色彩方面的信息,即便先將彩色圖轉灰度圖,再轉換回彩色圖,色彩信息一樣會丟失。

(5) 圖片的翻轉、旋轉、裁剪

a2=np.asarray(image2)

Image.fromarray(a2[::-1,::-1,:])
Out[85]: 
複製代碼

Image.fromarray(a2.transpose([1,0,2]))
Out[90]: 
複製代碼

Image.fromarray(a2[:150,:,:])
Out[91]:
複製代碼

以上示例展現了 左右翻轉+上下翻轉,左右翻轉+逆時針轉90°,截取上半部分 三種狀況,藉助倒序索引和軸交換的組合能夠獲得90°倍數旋轉和上下左右翻轉的全部組合情形。精確的旋轉須要使用矩陣運算,此處不做展開。
相關文章
相關標籤/搜索