1. 程式人生 > >ufunc函式(詳解 基礎學習 tcy)

ufunc函式(詳解 基礎學習 tcy)

ufunc函式 2018/11/22

# ufunc是universal function的縮寫,是一種能對陣列中每個元素進行操作的函式。
# Numpy內建的許多ufunc函式都是C語言實現的,計算速度非常快
==============================================================================
1.說明:
    計算單值建議採用Math庫函式,np.sin( )對應math.sin( );對於陣列元素,採用numpy庫函
    讀取ndarray陣列中單個元素(下標獲取轉換為python標準型別耗時)a.item(1,2)  #與a[1,2]類似

2.ufunc函式屬性方法 見備註
==============================================================================
3.編寫自定義ufunc函式:
# 基本形式
u_func = np.frompyfunc(func, nin, nout,otypes=[dtype1,dtype2..]#返回np.object
u_func = np.vectorize(pyfunc, otypes=None, doc=None, excluded=None, cache=False,signature=None)

# 第一步:定義函式
def MyAdd(x,y):
    return x+y

# 第二步:轉換
uMyAdd  =np.frompyfunc(MyAdd,2,1)#返回np.object型別,需要用a=a.astype()轉換為目的型別
uMyAdd1=np.vectorize(MyAdd,otypes=[np.int])

# 第三步:應用
a=np.array([1,2,3])
b=np.array([4,5,6])

c=uMyAdd(a,b)      # array([5, 7, 9], dtype=object)
c=c.astype(np.int)  # array([5, 7, 9])
c.dtype                   # dtype('int32')

d=uMyAdd1(a,b)    # array([5, 7, 9])
d.dtype                  # dtype('int32')

備註:
========================================================================
ufunc函式引數

out        #輸出
where   #布林陣列。True值表示計算該位置的ufunc,False值表示僅在輸出中保留該值。
axes     # 預設值是'same_kind'
order   #預設為'K'儘可能接近地匹配輸入的元素排序。
dtype
keepdims#True則減小的軸將作為尺寸為1的尺寸保留在結果中,只用於對輸入操作通用ufunc
subok     # 預設為true。如果設定為false,則輸出將始終是嚴格的陣列,而不是子型別。
extobj     #指定ufunc緩衝區大小
========================================================================
屬性(只讀)

np.add.__name__#函式名稱 'add'
np.add.__doc__   #函式文件
np.add.nin            #輸入引數數量2
np.add.nout         #輸出引數數量1
np.add.nargs       #引數數量3
np.add.ntypes     #型別數量22
np.add.types       #包含型別列表 [?,b,B,h,H,i,I,l,L,q,Q,e,f,d,g,F,D,G,M,m,M,O]
np.add.identity    #身份價值0
np.add.signature#廣義ufunc操作的核心元素的定義
========================================================================

ufunc方法
# ufunc函式方法只對兩個輸入、一個輸出的ufunc 函式有效,其他ufunc物件呼叫會ValueError
ufunc.reduce(a[, axis, dtype, out, keepdims])#減少軸數
ufunc.accumulate(array[, axis, dtype, out])    #陣列元素累計計算
ufunc.reduceat(a, indices[, axis, dtype, out]) #在單個軸上使用指定切片執行(區域性)縮減
ufunc.outer(A, B, **kwargs)#Apply the ufunc op to all pairs (a, b) with a in A and b in B.將ufunc OP應用於a和b在B中的所有對(a,b)
ufunc.at(a, indices[, b])      #對'index'指定的元素在運算元'a'上執行無緩衝的就地操作.

(1). reduce()#沿著指定軸對陣列進行操作,相當於將相應的操作放到該軸元素之間。

np.add.reduce([1,2,3])                         #1+2+3=6
np.add.reduce([[1,2,3],[4,5,6]])            #[1+4,2+5,3+6]=[5,7,9]
np.add.reduce([[1,2,3],[4,5,6]],axis=1) #[1+2+3,4+5+6]=[6,15]

(2). accumulate()#和reduce()類似,會保留中間結果:

np.add.accumulate([1,2,3])                         #[1,1+2,1+2+3]=[1,3,6]
np.add.accumulate([[1,2,3],[4,5,6]],axis=0) #array([[1, 2, 3],[5, 7, 9]], dtype=int32)
np.add.accumulate([[1,2,3],[4,5,6]],axis=1) #array([[ 1,  3,  6],[ 4,  9, 15]], dtype=int32)

(3). reduceat()方法計算多維reduce()的結果#通過 indices引數指定一系列的起始和終止位置。它的計算有些特別,,計算的方法如下:

if indices[i] < indices[i+1]:
    result[i] = <op>.reduce(a[indices[i]:indices[i+1]])
else:
    result[i] = a[indices[i]]

#result[-1]的計算如下:
<op>.reduce(a[indices[-1]:])
# 例:
a = np.array([1,2,3,4])
result = np.add.reduceat(a, indices=[0,1,0,2,0,3,0])
## result
array([1,2,3,3,6,4,10])

## 計算過程如下:
1 : a[0] -> 1
2 : a[1] -> 2
3 : a[0] + a[1] -> 1 + 2
4 : a[2] -> 3
5 : a[0] + a[1] + a[2] -> 1 + 2 + 3 = 6
6 : a[3] -> 4
7 : a[0] + a[1] + a[2] + a[4] - > 1 + 2 + 3 + 4 = 10

(4) ufunc.outer 將a的每個元素依次作用於b:通過函式
# 原理:
    C[i0,i1,...,i_m_1   ,j0,j1,...,j_n_1]=op(a[i0,i1,...,i_m_1],b[j0,j1,...,j_n_1])

# 對於a和b一維,這相當於:

r = empty(len(a),len(b))
for i in range(len(a)):
    for j in range(len(b)):
        r[i,j] = op(a[i], b[j]) # op = ufunc in question

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

array([[5, 6, 7], #1+[4,5,6]
          [6, 7, 8], #2+[4,5,6]
          [7, 8, 9]])#3+[4,5,6]

a=np.array([[1,2,3],[4,5,6]])
b=np.array([[11,12,13],[14,15,16]])
np.add.outer(a,b)

array([[[[12, 13, 14],     #1+[11,12,13]
             [15, 16, 17]],   #1+[14,15,16]

            [[13, 14, 15],    #2+[11,12,13]
             [16, 17, 18]],   #2+[14,15,16]

            [[14, 15, 16],    #3+[11,12,13]
             [17, 18, 19]]],  #3+[14,15,16]

           [[[15, 16, 17],    #4+[11,12,13]
             [18, 19, 20]],   #4+[14,15,16]

            [[16, 17, 18],   #5+[11,12,13]
             [19, 20, 21]],  #5+[14,15,16]

            [[17, 18, 19],   #6+[11,12,13]
             [20, 21, 22]]]])#6+[14,15,16]
=====================================================================