天天看點

Numpy 中 numpy.ndarray 四則運算--結構化數組

文章目錄

  • ​​一、四則運算​​
  • ​​二、matrix運算​​
  • ​​三、結構化數組​​
  • ​​四、Numpy自定義ufunc函數​​
  • ​​五、NumPy 字元串函數​​
  • ​​六、ufunc函數​​

以下隻是對一些常用函數的記錄:關于詳情請檢視

​​【NumPy使用者手冊】​​

一、四則運算

Numpy 中 numpy.ndarray 四則運算(+,-,*,/),與數學中的加減乘除一樣。不涉及矩陣運算。

注意:a_array/b_array 與M_array次元(a_array元素個數與M_array的行相同,同理b_array元素個數與M_array的列相同)

運算示例: :先廣播後加減(對應位置元素運算)

運算示例: 先廣播後乘除(對應位置元素運算)

import numpy as np


a_array = np.array([1,2,3])
b_array = np.array([[4],
                    [5],
                    [6]])

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

#============== numpy.ndarray數組四則運算都是:對應位置元素 ==================
print('相同次元數組直接相加(減)    --> a_array + a_array:\n',a_array + a_array)
print('不同次元數組先廣播再相加(減)--> a_array + b_array:\n',a_array + b_array)
print('不同次元數組先廣播再相加(減)--> a_array + M_array:\n',a_array + M_array)
print('不同次元數組先廣播再相乘(除)--> a_array * M_array:\n',a_array * M_array)

print('矩陣相乘:點積  --> np.dot(a_array,M_array):\n',np.dot(a_array,M_array))

'''
相同次元數組直接相加(減)    --> a_array + a_array:
 [2 4 6]
不同次元數組先廣播再相加(減)--> a_array + b_array:
 [[5 6 7]
  [6 7 8]
  [7 8 9]]
不同次元數組先廣播再相加(減)--> a_array + M_array:
 [[ 2  4  6]
  [ 5  7  9]
  [ 8 10 12]]
不同次元數組先廣播再相乘(除)--> a_array * M_array:
 [[ 1  4  9]
  [ 4 10 18]
  [ 7 16 27]]
矩陣相乘:點積--> np.dot(a_array,M_array):
 [30 36 42]
'''      

二、matrix運算

它們之間的 加減除 跟ndarray是一樣的,但乘法為矩陣乘法,Numpy數組中使用 np.dot() 實作矩陣乘法,同理matrix也可以使用 np.multiply() 實作一般的乘法

注意:mat_1的元素個數與 mat_N 列元素相同,同理 mat_2 元素個數與 mat_N 的行相同)

a_array*b_array

mat_1 = np.mat([1,2,3])

mat_N = np.mat([[1,2,3],
                [4,5,6],
                [7,8,9]])

print('矩陣相乘:點積 --> mat_1 * mat_N:\n',mat_1 * mat_N)
print('對應位置元素相乘 --> np.multiply(mat_1,mat_N):\n',np.multiply(mat_1,mat_N))

'''
======== 運算結果可以與上面對比 ========
矩陣相乘:點積 --> mat_1 * mat_N:
 [[30 36 42]]
對應位置元素相乘 --> np.multiply(mat_1,mat_N):
 [[ 1  4  9]
 [ 4 10 18]
 [ 7 16 27]]
'''      

報錯解決:(遇到這個問題,我當時是郁悶的,找了好久,原來是資料的dtype類型不同)

​​

​ValueError: operands could not be broadcast together with shapes (420,300) (420,)​

cov_mat = np.array(image_2d) - np.mean(image_2d, axis=1)

print("data.type:", type(image_2d).dtype)
print("mean.type:", typenp.mean(image_2d, axis=1)))

print("data.type:", image_2d.dtype)
print("mean.type:", np.mean(image_2d, axis=1).dtype)
===============================
data.type: <class 'numpy.ndarray'>
mean.type: <class 'numpy.ndarray'>

data.type: uint8
mean.type:      

三、結構化數組

結構化數組存儲的資料進行了序列化,擁有約C結構體一樣的通路速度。

C++/C 這樣定義一個結構體類型,裡面又許多不同的資料:

student = np.dtype([('name','S20'),  ('age',  'i1'),  ('marks',  'f4')]) 

相當于C語言中中:
struct student{
    char name[20];
    int age;    // 8位整型數
    float marks // 32位浮點數
};      

方法一:定義好的結構體類型并初始化對象

teacher = np.dtype([('name','U20'),('age','>i4'),('sex',int)])
CSTeachers = np.array([("張傑",50,False),("江志英",32,True),("盧罡",30,True)],dtype=teacher)      

方法二:批量初始化

import numpy as np


num_values = np.array([11,22,43,14,50,64,23,23,34,45],dtype=np.int32)
list_num = list(range(len(num_values)))


data = np.zeros(len(num_values),dtype={'names':['key_','value_'],
                                       'formats':['i4','i4']})
print('data.dtype:',data.dtype)

data['key_'] = num_values
data['value_'] = list_num

print('data:',data)
print('data:',data['key_'][0])

排序:
np.sort(data,order='value_')
====================================================
data.dtype: [('key_', '<i4'), ('value_', '<i4')]
data: [(11, 0) (22, 1) (43, 2) (14, 3) (50, 4) (64, 5) (23, 6) (23, 7) (34, 8) (45, 9)]
data: 11      

結構化數組–資料類型表

類型 字元代碼
bool ?, b1
int8 b, i1
uint8 B, u1
int16 h, i2
uint16 H, u2
int32 i, i4
uint32 I, u4
int64 q, i8
uint64 Q, u8
float16 f2, e
float32 f4, f
float64 f8, d
complex64 F4, F
complex128 F8, D
str a, S(S後面添加數字,表示字元串長度,不寫則為最大長度)
unicode U
object O
void V

四、Numpy自定義ufunc函數

使用 frompyfunc() 或者 vectorize()可以将計算單個元素的函數轉換成對數組中每個元素的ufunc函數

使用 frompyfunc(func,nin,nout) 将單值計算函數轉換成數組計算函數,其中func是單值計算函數,nin是func的輸入參數的個數,nout是func的傳回值的個數

# triangle_wave()是一個将x值轉換成三角波上對應的y值
def triangle_wave(x,c,c0,hc):
    x = x - int(x)
    if x >= c: 
        r =0.0
    elif x< c0: 
        r = x/c0*hc
    else: 
        r = (c-x)/(c-c0)*hc
    return r

x = np.linspace(0,2,1000)


''' 推導式直接使用函數生成數組 '''
y1 = np.array([triangle_wave(t,0.6,0.4,1.0) for t in x])


''' 使用np.frompyfunc生成數組 '''
triangle_ufunc1 = np.frompyfunc(triangle_wave,4,1)
y2 = triangle_ufunc1(x,0.6,0.4,1.0)


triangle_ufunc2 = np.vectorize(triangle_wave,otypes=[np.float])
y3 = triangle_ufunc2(x,0.6,0.4,1.0)


print(y2.dtype)                    # object
print(y2.astype(np.float).dtype)   # float64
print(y3.dtype)                    # float64      

由np.frompyfunc()轉換的函數傳回值是object,故需要顯式将其類型轉換為np.float

vectorize()類似于frompyfunc(),隻不過可以通過otypes指定傳回的數組的元素類型

五、NumPy 字元串函數

以下函數用于對 dtype 為 numpy.string_ 或 numpy.unicode_ 的數組執行向量化字元串操作。 它們基于 Python 内置庫中的标準字元串函數。這些函數在字元數組類(numpy.char)中定義。

函數 描述

​add()​

對兩個數組的逐個字元串元素進行連接配接

​multiply()​

傳回按元素多重連接配接後的字元串

​center()​

居中字元串

​capitalize()​

将字元串第一個字母轉換為大寫

​title()​

将字元串的每個單詞的第一個字母轉換為大寫

​lower()​

數組元素轉換為小寫

​upper()​

數組元素轉換為大寫

​split()​

指定分隔符對字元串進行分割,并傳回數組清單

​splitlines()​

傳回元素中的行清單,以換行符分割

​strip()​

移除元素開頭或者結尾處的特定字元

​join()​

通過指定分隔符來連接配接數組中的元素

​replace()​

使用新字元串替換字元串中的所有子字元串

​decode()​

數組元素依次調用​

​str.decode​

​encode()​

數組元素依次調用​

​str.encode​

小示例:

import numpy as np 
 
print ('連接配接兩個字元串:\n')
print (np.char.add(['hello'],[' xyz']))


print ('連接配接示例:')
print (np.char.add(['hello', 'hi'],[' abc', ' xyz']))
#=============================
連接配接兩個字元串:
['hello xyz']

連接配接示例:
['hello abc' 'hi xyz']      

numpy 中判斷某字元串 array 是否含有子字元串,詳情請點選:​​【NumPy字元串操作】。​​

​numpy.char.count(a, sub, start=0, end=None)​

​​ 該函數是用來計數 sub 在 a 中出現多少次。

​​

​numpy.char.count(a, sub, start=0, end=None) != 0​

​  該函數是用來子串sub 在 a 中是否出現。

import numpy as np

a = np.array(['abc', 'akjs', '23ha', 'sdfg', 'arge', '8908d', 'aaaab'], dtype='str')
np.char.count(a, 'a')
# array([1, 1, 1, 0, 1, 0, 4])

np.char.count(a, 'a') != 0
# array([ True,  True,  True, False,  True, False,  True])      

小示例二:

# 将其中字段為“text”這一列的空格替換掉(去除文本中間的所有空格)
area["text"] = np.char.replace(area["text"]," ","")


a = np.char.count(area["text"], 'SURAT') != 0
# 傳回布爾值,輸出如下:
'''
array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False,  True, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False])
'''42


b = np.char.find(area["text"],'SURAT',start = 0,end = None)
# 傳回0 或1,輸出如下:
'''
array([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  0,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1])
'''      

六、ufunc函數

​np.add.reduce​

​​

​np.add.accumulate​

累加:accumulate() 和 reduce()的關系,就像cumsum 和 sum 的關系,差別時是前者會保留中間結果。

reduceat()方法用于部分reduce計算,通過indices參數指定一系列的起始和終止位置。

​​

​np.add.reduceat​

​ 示例:

In [94]: arr = array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [95]: np.add.reduceat(arr,[0,5,8])
Out[95]: array([10, 18, 17], dtype=int32)      

outer() 計算兩個數組的交叉積–交叉差

arr0 = np.array([0, 1, 2, 1, 2])
arr1 = np.array([1, 3, 4, 2, 2])
arrX = np.multiply.outer(arr0,arr1)   # arr0 的每一個元素與 arr1 所有元素相乘,組成一行


arr7 = np.array([[67, 36, 57, 82],
                [39, 18, 18, 79],
                [73, 16, 38, 36]])

arr8 = np.array([ 35, 26, 45, 76, 17])
arr_ = np.subtract.outer(arr7,arr8)  # arr7 的每一個元素與 arr8 所有元素相減,組成一行

print('arrX:\n',arrX)
print('arr_:\n',arr_)

'''
arrX:
[[0 0 0 0 0]
[1 3 4 2 2]
[2 6 8 4 4]
[1 3 4 2 2]
[2 6 8 4 4]]

arr_:
[[[ 32  41  22  -9  50]
 [  1  10  -9 -40  19]
 [ 22  31  12 -19  40]
 [ 47  56  37   6  65]]

[[  4  13  -6 -37  22]
 [-17  -8 -27 -58   1]
 [-17  -8 -27 -58   1]
 [ 44  53  34   3  62]]

[[ 38  47  28  -3  56]
 [-19 -10 -29 -60  -1]
 [  3  12  -7 -38  21]
 [  1  10  -9 -40  19]]]
'''      
# Multi-dimensional array example 
import numpy as np 

a = np.array([[1,2], [3,4]]) 
b = np.array([[11, 12], [13, 14]]) 

print ('Array a:', a )
print ('Array b:', b )
print ('Inner product:',np.inner(a,b) )

#========================================================
Array a:
[[1 2]
[3 4]]

Array b:
[[11 12]
[13 14]]

Inner product:
[[35 41]
[81 95]]

計算示範:
1*11+2*12, 1*13+2*14 
3*11+4*12, 3*13+4*14      

繼續閱讀