Numpy中矩陣的基本操作
Numpy
python及numpy的一系列安裝環境省略…
numpy的介紹鏈接:https://numpy.org
直接代碼配着註釋操作,都是一些非常基礎的操作。
更多學習可參考:https://www.runoob.com/numpy/numpy-tutorial.html
一、矩陣的創建
Python提供了list容器,可以當作數組使用。但列表中的元素可以是任何類型數據,因此列表保存的是對象的指針。這就造成,要保存一個簡單的列表[1, 2, 3, 4, 5],需要五個指針和五個整數對象。對於數值運算來說,這種結構顯然不夠高效。Python雖然也提供了array模塊,但其只支持一維數組,不支持多維數組,也沒有各種運算函數。因而不適合數值運算。NumPy的出現彌補了這些不足,所以NumPy中array的一個特點就是,數組中元素的類型必須一致。
下面就是用NumPy中array()來創建的多維數組:
import numpy as np # 導入numpy包
a = np.array([1, 2, 3]) # 輸入一維矩陣,英文單詞array意思爲:陣列,矩陣的意思。所以方法array(),也就顧名思義了。
print(a) # 輸出結果爲:[1 2 3]
# 構造二維的矩陣。
b = np.array([[1, 2, 3],
[4, 5, 6]])
print(b)
# 輸出如下:
# [[1 2 3]
# [4 5 6]]
# 構造三維矩陣:
c = np.array([[[1, 2, 3], [4, 5, 6]],
[[7, 8, 9], [10, 11, 12]]])
print(c)
# 輸出如下:
# [[[ 1 2 3]
# [ 4 5 6]]
# [[ 7 8 9]
# [10 11 12]]]
總結:一維矩陣一層中括號,二維矩陣兩層中括號,三維矩陣三層中括號,繼續下去一樣,輸入幾維矩陣就是幾層中括號。常用的只是一維和二維。
二、矩陣屬性查看及簡單應用
1、矩陣屬性查看
import numpy as np # 導入numpy包
# 括號中輸入一個二維矩陣。
array = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(array)
# 輸出結果如下:
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
print(array.ndim) # array.ndim查看矩陣的維度。
# 輸出結果:2
print(array.shape) # array.shape查看矩陣的形狀,返回幾行幾列的矩陣。
# 輸出結果:(3,3)
print(array.size) # array.size查看元素個數。
# 輸出結果:9
print(array.dtype) # array.dtype查看矩陣中元素類型。
# 輸出結果:int32
注:numpy的這些屬性與英語單詞或單詞縮寫的意思都是保持一致的,有一定的英語基礎會很容易記這些屬性。
2、基本屬性應用
import numpy as np # 導入numpy包
# 輸入一維矩陣,參數dtype=np.int32定義元素值的類型。
a = np.array([1, 2, 3], dtype=np.int32)
print(a.dtype) # 返回:int32
print(a) # 返回:[1 2 3]
b = np.array([1, 2, 3], dtype=np.float)
print(b.dtype) # 返回:float64
print(b) # 返回:[1. 2. 3.]
# 矩陣b與矩陣a相比較,返回的元素值都加了點,爲浮點型數值。
# zeros()返回一個全爲零的矩陣,參數(2, 3)表示矩陣規格爲2行3列。
zero = np.zeros((2, 3))
print(zero)
# 返回結果:
# [[0. 0. 0.]
# [0. 0. 0.]]
# ones()返回一個全爲1的矩陣,參數(2, 4)同樣表示矩陣規格,2行4列
one = np.ones((2, 4))
print(one)
# 返回結果如下:
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# empty()返回一個空矩陣,參數(2, 3)同樣表示矩陣規格。
empty = np.empty((2, 3))
print(empty)
# 返回結果:
# [[0. 0. 0.]
# [0. 0. 0.]]
注:與zeros()不同,zeros矩陣中,每個數值都是0。比如:用5除以矩陣中數值會報錯的那種。empty()雖然返回矩陣每個數值也都是0,但用一個數除以矩陣中的0不會報錯。
3、生成矩陣
兩種方式生成ndarray矩陣:
(1)numpy.arange(start, stop, step, dtype = None)
參數:
- start 開始位置,數字,可選項,默認起始值爲0。
- stop 停止位置,數字。
- step 步長,數字,可選項, 默認步長爲1,如果指定了step,則還必須給出start。
- dtype 輸出數組的類型。 如果未給出dtype,則從其他輸入參數推斷數據類型。
numpy中的arange()屬性與python中的range()很像,具體如下:
import numpy as np # 導入numpy包
a = np.arange(10) # 返回一維數組,不包括10,從0~9。
print(a) # 返回結果:[0 1 2 3 4 5 6 7 8 9]
b = np.arange(4, 10) # 返回一維數組,不包括10,從4~9。
print(b) # 返回結果:[4 5 6 7 8 9]
c = np.arange(1, 15, 3) # 返回一維數組,不包括15,從1~15中,依次加3取數。
print(c) # 返回結果:[ 1 4 7 10 13]
d = np.arange(8).reshape(2, 4) # 單詞reshape爲重新塑造的意思,即將原來0~7的一維數組,從新塑造成2行4列的數組。
print(d)
# 返回結果如下:
# [[0 1 2 3]
# [4 5 6 7]]
(2)numpy.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype=None)
參數:
- start:scalar類型(標量),這個數參數表示這個序列的開始值。
- stop:scalar類型。如果endpoint=True,那麼stop就是序列的終止數值。當endpoint = False時,返回值中不包含最後一個端點,並且步長會改變。
- num:int型,可選參數,默認值爲50。表示要生成的樣本數,必須是非負值。
- endpoint:bool類型。可選參數,默認值爲True,這時stop就是最後的樣本。爲False時,不包含stop的值。
- retstep:bool類型。可選參數,默認值爲True,這時返回值是(samples,step),前面的是數組,後面是步長。
- dtype:表示輸出的數組的數據類型,如果沒有給出就從其他輸入中推斷輸出的類型。
返回值:
- samples:ndarray類型。在[start,stop]閉區間,或者[start,stop)半閉合區間中,數量爲num,步長相等的樣本。至於包不包含stop取決於endpoint參數的取值。
- step:float類型。可選。只有restep參數取值爲True時纔會返回這個返回值,表示樣本中步長。
例子:
import numpy as np
# 包含了endpoint(末尾數49)的情況,對於這種情況,步長就是1+24x=49,也就是stop參數跟start參數相差了(num-1),並且返回的樣本中包含stop的值。
a,b = np.linspace(1,49,25,True,True)
print(a)
# 輸出結果:
[ 1. 3. 5. 7. 9. 11. 13. 15. 17. 19. 21. 23. 25. 27. 29. 31. 33. 35.37. 39. 41. 43. 45. 47. 49.]
print(b) # 輸出結果:2.0
# 不包含了endpoint(末尾數49)的情況,注意此時的步長返回值,與上一個例子不一樣。步長是1+25y=49,也就是stop參數跟start參數相差了(num),並且返回的樣本中不包含stop的值。
sample,step = np.linspace(1,49,25,False,True)
print(sample)
# 輸出結果如下:
[ 1. 2.92 4.84 6.76 8.68 10.6 12.52 14.44 16.36 18.28 20.2 22.12 24.04 25.96 27.88 29.8 31.72 33.64 35.56 37.48 39.4 41.32 43.24 45.16
47.08]
print(step) # 輸出結果:1.92
三、矩陣的運算
numpy的基本運算:
import numpy as np # 導入numpy包
# 手動輸入兩個矩陣,進行加、減、乘、除、冪運算、取整、取餘以及矩陣乘法與轉置的運算操作。
a = np.array([[1, 2, 3],
[4, 5, 6]])
b = np.array([[1, 1, 2],
[2, 3, 3]])
# 其中加、減、乘、除、冪運算、取整、取餘,爲一一對應運算,要求兩個矩陣的行數與列數相同。
print(a + b)
# 對應相加後的結果爲:
# [[2 3 5]
# [6 8 9]]
print(a - b)
# [[0 1 1]
# [2 2 3]]
print(a * b)
# 這個注意一下,與線性代數中矩陣相乘不同,此處爲一一對應相乘。矩陣運算在下面。
# [[ 1 2 6]
# [ 8 15 18]]
print(a ** b)
# 同樣對應取冪,1的1次方,2的1次方,3的2次方...
# [[ 1 2 9]
# [ 16 125 216]]
print(a / b)
# [[1. 2. 1.5 ]
# [2. 1.66666667 2. ]]
print(a // b)
# [[1 2 1]
# [2 1 2]]
print(a % b)
# [[0 0 1]
# [0 2 0]]
# 下面是矩陣加、減、乘、除、取冪、取整、取餘一個數,規則一樣。
print(a + 2)
# 所有元素都加上2。
# [[3 4 5]
# [6 7 8]]
# ......中間略去......
print(a % 2)
# 同樣每個數都對2取餘。
# [[1 0 1]
# [0 1 0]]
c = a > 3
print(c)
# 所有元素與3比較,比3大返回True,否則返回False。
# [[False False False]
# [ True True True]]
# 下面纔是常用的矩陣運算,需要有一點線性代數或矩陣基礎,百度一下矩陣運算,看一下規則,很簡單。
d = np.ones((3, 4)) # 生成一個3行4列,全爲1的矩陣。
# 矩陣乘法兩種方式
# 第一種:
print(np.dot(a, d))
# 第二種:
print(a.dot(d))
# 運算規則,第一個矩陣的列必須與第二個矩陣的行相等才能運算。此矩陣爲2行3列*3行4列。
# [[ 6. 6. 6. 6.]
# [15. 15. 15. 15.]]
# 矩陣轉置,本質爲行列互換。兩種方式。
# 第一種:
print(a.T)
# 第二種:
print(np.transpose(a))
# [[1 4]
# [2 5]
# [3 6]]
四、隨機生成矩陣及矩陣性質的查看
import numpy as np
# 下面數都是隨機生成的,每次運行的值都會不一樣。
a = np.random.random((3, 2)) # 生成3行2列的矩陣,數值默認0-1之間。
print(a)
# [[0.19439999 0.61997541]
# [0.77285803 0.78376932]
# [0.53661576 0.02555825]]
# 生成3行2列的矩陣,數值都符合標準正太分佈的隨機數。
b = np.random.random(size=(3, 2))
print(b)
# [[0.7225062 0.11323939]
# [0.59477429 0.8096198 ]
# [0.36840557 0.46298932]]
# 生成值爲整數的3行2列矩陣,數值範圍從0-10。
c = np.random.randint(0, 10, size=(3, 2))
print(c)
# [[9 9]
# [8 1]
# [4 3]]
print(np.sum(a)) # 所有元素相加。結果:2.9331767671479536
print(np.min(a)) # 所用元素中最小值。結果:0.025558249120347765
print(np.max(a)) # 所有元素中最大值。結果:0.7837693202695092
print(np.sum(a, axis=0)) # 單詞axis爲軸,座標軸的意思,值爲0表示去縱列,每列求和。結果:[1.50387379 1.42930298]
print(np.sum(a, axis=1)) # 每行求和。結果:[0.8143754 1.55662735 0.56217401]
print(np.argmin(a)) # 最小元素所在的索引,從零開始數,第一行數完數下面一行。結果:5
print(np.argmax(a)) # 最大元素所在的索引,從零開始數,第一行數完數下面一行。結果:3
print(np.mean(a)) # 所有元素平均值。結果0.4888627945246589
print(a.mean()) # 與上一個方法一樣。結果:0.4888627945246589
print(np.median(a)) # 求中位數。結果:0.5782955853721933
print(np.sqrt(a)) # 所有元素開根號。
# 返回結果如下:
# [[0.44090815 0.78738517]
# [0.87912345 0.88530747]
# [0.73254062 0.15986948]]
import numpy as np
# 一維數組中
d = np.random.randint(0, 10, size=(1, 10))
print(d) # 結果:[[5 3 4 7 4 8 6 1 6 9]]
print(np.sort(d)) # 排序,從小到大。結果:[[1 3 4 4 5 6 6 7 8 9]]
print(np.clip(d, 2, 7)) # 此數組中比2小的都變成2,比7大的都變成7,2-7不變。結果:[[5 3 4 7 4 7 6 2 6 7]]
# 二維數組中
e = np.random.randint(0, 10, size=(2, 5))
print(e)
# [[8 5 2 0 7]
# [4 8 1 8 9]]
print(np.sort(e)) # 每行單獨排列。
# [[0 2 5 7 8]
# [1 4 8 8 9]]
print(np.clip(e, 2, 7)) # 二維數組中比2小的都變成2,比7大的都變成7,2-7不變。
# [[7 5 2 2 7]
# [4 7 2 7 7]]
五、矩陣的索引
import numpy as np
# 生成一個一維數組
a = np.arange(2, 14)
# 下面與python數組一致。
print(a) # 結果:[ 2 3 4 5 6 7 8 9 10 11 12 13]
print(a[2]) # 從0開始數,打印數組中索引爲2的元素。結果:4
print(a[1:4]) # 打印索引從1-4的元素,不包括索引爲4的值。結果:[3 4 5]
print(a[2:-1]) # 打印索引從2到最後一個的元素,不包含最後一個。結果:[ 4 5 6 7 8 9 10 11 12]
print(a[:5]) # 打印從0好索引開始到5號索引的值,不包括5好索引。結果:[2 3 4 5 6]
print(a[-2:]) # 打印最後兩個索引的值。結果:[12 13]
# 二維數組的索引查找
b = a.reshape(3, 4)
print(b)
# [[ 2 3 4 5]
# [ 6 7 8 9]
# [10 11 12 13]]
print(b[1]) # 索引從0行0列開始數,取二維數組第1行。結果:[6 7 8 9]
print(b[1][1]) # 索引從0行0列開始數,取二維數組索引爲行1與列1的數。結果:7
print(b[1, 1]) # 與上述方法一致。結果:7
print(b[:, 2]) # 取所有行第二列。結果:[ 4 8 12]
# 打印二維數組,每次打印一行,相當於迭代3次。
for i in b:
print(i)
# [2 3 4 5]
# [6 7 8 9]
# [10 11 12 13]
# 利用轉置,打印二維數組的列,相當於迭代四次。
for i in b.T:
print(i)
# [ 2 6 10]
# [ 3 7 11]
# [ 4 8 12]
# [ 5 9 13]
# 逐個元素打印,相當於迭代12次。
for i in b.flat:
print(i)
# 2 3 4 5 6 7 8 9 10 11 12 13
六、矩陣合併
import numpy as np
# 準備三個矩陣a, b, c,幾維的矩陣都可以,下面以一維爲例。
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])
# 矩陣的垂直合併。
d = np.vstack((a, b, c)) # 注意有兩個括號,寫快容易忽略。
print(d.shape)
# (3, 3)
print(d)
# [[1 2 3]
# [4 5 6]
# [7 8 9]]
# 矩陣的水平合併
e = np.hstack((a, b, c))
print(e.shape)
# (9,)
print(e)
# [1 2 3 4 5 6 7 8 9]
# 一種可以指定,水平合併還是垂直合併的方法,concatenate()。
# 此方法要求:要合併的矩陣必須是相同維度的矩陣,一維矩陣和二維矩陣不能合併。還要具有相同的行數和列數。
# 此方法不適合一維矩陣之間的合併。
array1 = np.array([[1, 2, 3],
[4, 5, 6]])
array2 = np.array([[7, 8, 9],
[10, 11, 12]])
f = np.concatenate((array1, array2), axis=0) # 參數axis爲0,垂直合併。
print(f)
# [[ 1 2 3]
# [ 4 5 6]
# [ 7 8 9]
# [10 11 12]]
g = np.concatenate((array1, array2), axis=1) # 參數axis爲1,水平合併。
print(g)
# [[ 1 2 3 7 8 9]
# [ 4 5 6 10 11 12]]
'''一維數組的轉置還是它本身'''
# 數據的升維
# np.newaxis在行的位置,按行升維。其中":"從第幾個元素到第幾個元素,不寫默認全部。
new_a = a[np.newaxis, :]
print(new_a.shape)
# (1, 3)
print(new_a)
# [[1 2 3]]
# np.newaxis在列的位置,按行升維。
new_a = a[:, np.newaxis]
print(new_a.shape)
# (3, 1)
print(new_a)
# [[1]
# [2]
# [3]]
# 保證數據至少是二維,或更高維的方法。
# 默認按照a[np.newaxis, :]方式升維。
new_a = np.atleast_2d(a)
print(new_a.shape)
# (1, 3)
print(new_a)
# [[1 2 3]]
七、矩陣分割
import numpy as np
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 將垂直方向,分成三段。
a1, a2, a3 = np.vsplit(a, 3)
print(a1) # [[0 1 2 3]]
print(a2) # [[4 5 6 7]]
print(a3) # [[ 8 9 10 11]]
# 將水平方向分成兩段。
a4, a5 = np.hsplit(a, 2)
print(a4)
# [[0 1]
# [4 5]
# [8 9]]
print(a5)
# [[ 2 3]
# [ 6 7]
# [10 11]]
# 參數指定垂直方向還是水平方向。
a1, a2 = np.split(a, 2, axis=1)
# 參數(要分的矩陣,分的份數,水平方向上切開)
print(a1)
# [[0 1]
# [4 5]
# [8 9]]
print(a2)
# [[ 2 3]
# [ 6 7]
# [10 11]]
a3, a4, a5 = np.split(a, 3, axis=0)
# 參數(要分的矩陣,分的份數,水平方向上切開)
print(a3)
# [[0 1 2 3]]
print(a4)
# [[4 5 6 7]]
print(a5)
# [[ 8 9 10 11]]
'''以上的分割方法都是平均分,參數要看好,否則會報錯。'''
# 非平均分
a7, a8, a9 = np.array_split(a, 3, axis=1)
print(a7)
# [[0 1]
# [4 5]
# [8 9]]
print(a8)
# [[ 2]
# [ 6]
# [10]]
print(a9)
# [[ 3]
# [ 7]
# [11]]
八、矩陣的的淺拷貝與深拷貝
import numpy as np
# 淺拷貝
a = np.array([1, 2, 3])
b = a # 共享地址,b指向a的地址,不開闢新的內存,稱爲淺拷貝。
b[0] = 5 # 將b的第一個元素賦值爲5。發現兩個矩陣都改變。
print(a)
# [5 2 3]
print(b)
# [5 2 3]
# 深拷貝
c = a.copy() # 開闢了一個內存,c矩陣獨立與a矩陣,稱爲深拷貝。
c[0] = 6 # 只有c矩陣改變,不影響a矩陣。
print(a)
# [5 2 3]
print(c)
# [6 2 3]
都是一些最簡單基礎的操作!