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]

都是一些最簡單基礎的操作!

發佈了6 篇原創文章 · 獲贊 0 · 訪問量 375
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章