Python 的 Numpy 數值計算

1. Numpy 介紹

  Numpy(Numerical Python),是 Python 科學計算的基礎包。Mumpy 主要提供了以下內容:

  • 快速高效的多維數組對象 ndarray。
  • 對數組執行元素級計算以及直接對數組執行科學計算的函數。
  • 線性代數、傅里葉變換及隨機數生成的功能。
  • 將 C、C++、Fortran 代碼集成到 Python 的工具。
  • 讀寫硬盤上基於數組數據集的工具。

  Numpy 是用於科學計算的基礎模塊,不但能夠完成科學計算的任務,而且能夠被用作高效的多維數據容器,可以用於存儲和處理大型矩陣。Numpy 的數據容器可以保存任意類型的數據,所以可以整合各種數據。

Numpy 官網介紹
Numpy 1.17 官方手冊

2. Numpy 數組

  Python 提供了一個 array 模塊。array 和 list 不同,它直接保存數值,和 C 語言的一位數組比較類似。但是由於 Python 的 array 模塊不支持多維,也沒有各種運算函數,所以也不適合做數值運算。Numpy 提供了一種存儲單一數據類型的多維數組——ndarray。
  Numpy 提供了兩種基本對象:ndarray(N-dimensional Array Object)和 ufunc(Universal Function Object)。ndarray 是存儲單一數據類型的多維數組,而 ufunc 是能夠對數組進行處理的函數。

2.1 數組屬性

常用屬性 說明
shape 返回 tuple,返回數組維度的元組。如:(m,n) ,表示 m 行 n 列
ndim 返回 int,表示數組的維度
size 返回 int,表示數組中元素的個數
dtype 返回 data-type,表示數組元素的數據類型
itemsize 返回 int,表示一個數組元素的大小(以字節爲單位)
nbytes 返回 int,表示數組元素消耗的總字節數

2.2 創建數組

numpy.array(object,dtype=None,cope=True,order='K',subok=False,ndimn=0)

官方文檔

# 導入Numpy庫
import numpy as np

# 創建一維數組
arr1 = np.array([1,2,3,4])
print('創建的一維數組爲:',arr1)

# 創建二維數組
arr2 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print('創建的二維數組爲:\n',arr2)

# 查看數組屬性
print('數組的維數爲:',arr2.ndim)
print('數組的維度爲:',arr2.shape)
print('數組的元素個數爲',arr2.size)
print('數組的元素類型爲',arr2.dtype)
print('數組每個元素的大小爲',arr2.itemsize)
print('數組元素消耗的總字節數爲',arr2.nbytes)

# 重新設置數組的shape屬性
arr2.shape = 4,3
print('重新設置 shape 後的 arr2 爲:\n',arr2)

在這裏插入圖片描述
  上面的例子都是創建一個 Python 序列,然後通過 array 函數轉換爲數組,這樣做效率不高,因此 Numpy 提供了許多專門用來創建數組的函數。

# 使用arange函數創建數組(開始值,終值,步長(不包括終值))
print('使用arange函數創建的數組爲:\n',np.arange(0,1,0.1))

# 使用linspace函數創建數組(開始值,終值,元素個數(包括終值))
print('使用linspace函數創建的數組爲:\n',np.linspace(0,1,10))

# 使用logspace函數創建等比數列(開始值(1——10^1),終值,元素個數(包括終值)))
print('使用logspace函數創建等比數列爲:\n',np.logspace(1,2,10))
	
# 特殊數組
print('使用zeros函數創建的全0數組爲:\n',np.zeros((2,3)))
print('使用ones函數創建的全1數組爲:\n',np.ones((2,3)))
print('使用eye函數創建的數組爲:\n',np.eye(3))
print('使用diag函數創建的數組爲:\n',np.diag([1,2,3,4]))

在這裏插入圖片描述
數組數據類型轉換

# 數組數據類型轉換
print('轉換結果爲:',np.float(42))
print('轉換結果爲:',np.int8(42.0))
print('轉換結果爲:',np.bool(42))
print('轉換結果爲:',np.bool(0))
print('轉換結果爲:',np.float(True))
print('轉換結果爲:',np.float(False))

在這裏插入圖片描述

2.3 生成隨機數

# 生成隨機數([0,1))
print('生成隨機數組爲:\n',np.random.random(10))
print('生成服從均勻分佈的隨機數組爲:\n',np.random.rand(3,4))
print('生成服從正態分佈的隨機數組爲:\n',np.random.randn(3,4))

# 生成隨機數(給定範圍(不包括上限))
print('生成給定上下限的隨機數組爲:\n',np.random.randint(2,10,size=[2,5]))

在這裏插入圖片描述

2.4 訪問數組元素

# 使用索引訪問一維數組
arr = np.arange(10)
print('創建的一維數組爲:',arr)
print('索引結果爲:',arr[5])
print('索引結果爲:',arr[:5])
print('索引結果爲:',arr[5:])
print('索引結果爲:',arr[-1])      # 數組最後一個元素
print('索引結果爲:',arr[3:5])
print('索引結果爲:',arr[1:-1:2])  # 第三個參數爲步長
print('索引結果爲:',arr[5:1:-2])  # 步長爲負數時,開始下標必須大於結束下標
arr[2:4] = 100,101
print('修改後的一維數組爲:',arr)  # 下標還可以修改元素的值

# 使用索引訪問多維數組
arr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print('創建的二維數組爲:\n',arr)
print('索引結果爲:',arr[0,2:4])   # 索引第0行中的第2列和第3列元素
print('索引結果爲:',arr[1:,1:])
print('索引結果爲:',arr[:,2])
print('索引結果爲:',arr[1,(0,2,3)])

在這裏插入圖片描述

2.5 變換數組的形態

# 改變數組形狀(reshape函數改變原始數組形狀的同時不改變原始數據的值)
arr = np.arange(12)
print('創建的一維數組爲:',arr)
print('新的數組爲:\n',arr.reshape(3,4))

# 使用ravel函數展平數組
arr = np.arange(12).reshape(3,4)
print('創建的二維數組爲:\n',arr)
print('數組展平後:',arr.ravel())

# 使用flatten函數展平數組(可以選擇橫向或縱向)
print('數組橫向展平後:',arr.flatten())
print('數組縱向展平後:',arr.flatten('F'))

# 使用hstack函數和vstack函數實現數組橫向與縱向組合
arr1 = np.arange(12).reshape(3,4)
print('創建的數組1爲:\n',arr1)
arr2 = arr1*3
print('創建的數組2爲:\n',arr2)
print('橫向組合爲:\n',np.hstack((arr1,arr2)))
print('縱向組合爲:\n',np.vstack((arr1,arr2)))

# 使用concatenate函數實現數組橫向與縱向組合,axis默認爲0,縱向
print('橫向組合爲:\n',np.concatenate((arr1,arr2),axis=1))
print('縱向組合爲:\n',np.concatenate((arr1,arr2),axis=0))

# 使用hsplit函數和vsplit函數實現橫向與縱向分割數組,平均分割
arr = np.arange(16).reshape(4,4)
print('創建的二維數組爲:\n',arr)
print('橫向分割爲:\n',np.hsplit(arr,2))
print('縱向分割爲:\n',np.vsplit(arr,2))

# 使用split函數實現橫向與縱向分割數組,平均分割
print('橫向分割爲:\n',np.split(arr,2,axis=1))
print('縱向分割爲:\n',np.split(arr,2,axis=0))

在這裏插入圖片描述

3. Numpy 矩陣和通用函數

  在 Numpy 中,矩陣(matrix)是數組(ndarray)的子類。矩陣是繼承數組對象的二維數組對象。注意:官方文檔中不再建議使用此類,即使對於線性代數也是如此。而是使用常規數組,將來可能會刪除此類!

3.1 矩陣屬性

說明:因爲矩陣繼承自數組,所以矩陣具有數組的所有的屬性,以下展示矩陣特有的屬性。

常用屬性 說明
T 返回自身的轉置矩陣
H 返回自身的共軛矩陣
I 返回自身的逆矩陣
A 返回自身數據的二維數組的一個視圖
A1 返回自身數據一維數組的一個視圖(展開)

3.2 創建矩陣

# 使用mat函數和matrix函數創建矩陣
matr1 = np.mat("1 2 3;4 5 6;7 8 9")  # 使用分號隔開數據
print('創建的矩陣1爲:\n',matr1)
matr2 = np.matrix([[1,2,3],[4,5,6],[7,8,9]])
print('創建的矩陣2爲:\n',matr2)

# 使用bmat函數創建矩陣(小矩陣合成大矩陣)
print('創建的矩陣3爲:\n',np.bmat("matr1 matr2;matr1 matr2"))

# 矩陣運算
print('矩陣數乘的結果爲:\n',matr1*3)
print('矩陣相加的結果爲:\n',matr1+matr2)
print('矩陣相減的結果爲:\n',matr1-matr2)
print('矩陣相乘的結果爲:\n',matr1*matr2)
print('矩陣對應元素相乘的結果爲:\n',np.multiply(matr1,matr2))

# 查看矩陣屬性
print('矩陣1的轉置矩陣爲:\n',matr1.T)
print('矩陣1的共軛轉置矩陣爲:\n',matr1.H)  # 實數的共軛就是其本身
print('矩陣1的逆矩陣爲:\n',matr1.I)
print('矩陣1的二維數組爲:\n',matr1.A)
print('矩陣1的一維數組爲:',matr1.A1)

在這裏插入圖片描述

3.3 ufunc 函數

   ufunc 函數全稱爲通用函數,是一種能夠對數組中所有元素進行操作的函數。ufunc 函數是針對數組進行操作,並以 Numpy 數組作爲輸出,因此不需要對數組每一個元素都進行操作。所以使用 ufunc 函數比使用 math 庫中函數高效的多。

3.3.1 常用 ufunc 函數運算

  常用的 ufunc 函數有四則運算、比較運算和邏輯運算。

# 數組的四則運算
x = np.array([1,3,5])
y = np.array([2,3,4])
print('數組相加的結果爲:',x + y)
print('數組相減的結果爲:',x - y)
print('數組相乘的結果爲:',x * y)
print('數組相除的結果爲:',x / y)
print('數組冪運算的結果爲:',x ** y)

# 數組的比較運算
print('數組比較的結果爲:',x < y)
print('數組比較的結果爲:',x > y)
print('數組比較的結果爲:',x == y)
print('數組比較的結果爲:',x >= y)
print('數組比較的結果爲:',x <= y)
print('數組比較的結果爲:',x != y)

# 數組的邏輯運算,np.all()表示and,np.any()表示or
print("數組邏輯運算結果爲:",np.all(x == y))
print("數組邏輯運算結果爲:",np.any(x == y))

在這裏插入圖片描述

3.3.2 ufunc 函數的廣播機制

  廣播(Broadcasting)是指不同形狀的數組之間執行算數運算的方式。當使用 ufunc 函數進行數組計算時,ufunc 函數會對兩個數組的對應元素進行計算。進行這種運算的前提是兩個數組的 shape 一致。若兩個數組的 shape 不一致,則 Numpy 會實行廣播機制。

廣播機制四個原則:

  1. 讓所有輸入數組向其中 shape 最長的數組看齊,shape 中不足的部分通過在前面加 1 補齊。
  2. 輸出數組的 shape 是輸入數組 shape 的各個軸上的最大值。
  3. 如果輸入數組的某個軸和輸出數組的對應軸的長度相同或者長度爲 1 ,則這個數組能夠用來計算,否則出錯。
  4. 當輸入數組的某個軸的長度爲 1 時,沿着此軸運算時使用此軸的第一組值。
# 一維數組的廣播機制
arr1 = np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
print('創建的數組1爲:\n',arr1)
print('數組1的形狀爲:',arr1.shape)
arr2 = np.array([1,2,3])
print('創建的數組2爲:\n',arr2)
print('數組2的形狀爲:',arr2.shape)
print('數組1和2相加的結果爲:\n',arr1 + arr2)
arr3 = np.array([2])
print('創建的數組3爲:\n',arr3)
print('數組3的形狀爲:',arr3.shape)
print('數組1和3相加的結果爲:\n',arr1 + arr3)

print("--------------------------------------")

# 二維數組的廣播機制
arr1 = np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
print('創建的數組1爲:\n',arr1)
print('數組1的形狀爲:',arr1.shape)
arr2 = np.array([1,2,3,4]).reshape(4,1)
print('創建的數組2爲:\n',arr2)
print('數組2的形狀爲:',arr2.shape)
print('數組1和2相加的結果爲:\n',arr1 + arr2)

在這裏插入圖片描述

4. 利用 Numpy 進行統計分析

4.1 讀/寫文件

save 函數以二進制的格式保存數據(文件擴展名 .npy,若將多個數組保存到一個文件,可以使用 savez 函數,文件擴展名 .npz),load 函數從二進制的文件中讀取數據。

np.save(file, arr, allow_pickle=True, fix_imports=True)

save 函數官方文檔

np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII')

load 函數官方文檔

# 二進制數據存儲
arr = np.arange(100).reshape(10,10)
np.save("save_arr",arr)

# 多個數組存儲
arr1 = np.array([[1,2,3],[2,3,4]])
arr2 = np.arange(0,1.0,0.1)
np.savez("savez_arr",arr1,arr2)

# 二進制文件讀取
loaded_data = np.load("save_arr.npy")
print('讀取的數組爲:\n',loaded_data)

# 讀取含有多個數組的文件
loaded_data1 = np.load("savez_arr.npz")
print('讀取的數組1爲:\n',loaded_data1['arr_0'])
print('讀取的數組2爲:\n',loaded_data1['arr_1'])

在這裏插入圖片描述
  在實際的數據分析中,更多地使用文本格式的數據,如 .txt,.csv 格式,因此使用 savetxt 函數、loadtxt 函數、genfromtxt 函數執行對文本格式數據的讀取任務。

np.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='n', header='', footer='', 
			comments='# ', encoding=None)

savetxt 函數官方解釋

  loadtxt 函數執行相反的操作,即把文件加載到一個二維數組。genfromtxt 函數和 loadtxt 函數相似,但它面向的是結構化數組和缺失數據。

# 文件存儲與讀取
arr = np.arange(0,12,0.5).reshape(4,-1)  # 一個形狀的尺寸可以是-1,在這種情況下,該值是從數組的長度和剩餘維度推斷出來
print('創建的數組爲:\n',arr)
np.savetxt("arr.txt",arr,fmt="%d",delimiter=",")  # fmt="%d" 表示保存爲整數
loaded_data = np.loadtxt("arr.txt",delimiter=",")
print('讀取的數組爲:\n',loaded_data)

# 使用 genfromtxt 函數讀取數組
loaded_data = np.genfromtxt("arr.txt",delimiter=",")
print('讀取的數組爲:\n',loaded_data)

在這裏插入圖片描述

4.2 使用函數進行簡單的統計分析

4.2.1 排序

  Numpy 的排序有兩種方式,分別爲 直接排序間接排序。直接排序是指對數值直接排序;間接排序是指根據一個或多個鍵對數據集進行排序。在 Numpy 中,直接排序經常使用 sort 函數,間接排序經常使用 argsort 函數和 lexsort 函數。

# 使用sort函數進行排序(無返回值,原始數據會改變)
np.random.seed(42)  # 設置隨機種子
arr = np.random.randint(1,10,size = 10)
print("創建的隨機數組爲:\n",arr)
arr.sort()
print('排序後的數組爲:\n',arr)
arr = np.random.randint(1,10,size = (3,3))
print('創建的數組爲:\n',arr)
arr.sort(axis = 1)      # 沿着橫軸排序
print('排序後的數組爲:\n',arr)
arr.sort(axis = 0)      # 沿着縱軸排序
print('排序後的數組爲:\n',arr)

# 使用 argsort 函數進行排序(返回值爲索引數組,是重新排序值的下標)
arr = np.array([2,3,6,8,0,7])
print('創建的數組爲:',arr)
print('排序後的數組爲:\n',arr.argsort())  

# 使用lexsort函數進行排序(返回值爲索引數組,可以一次性對滿足多個鍵的數組執行間接排序)
# 序列中的最後一個鍵用於主排序順序、輔助排序順序的倒數第二個鍵等。
a = np.array([3,2,6,4,5])
b = np.array([50,30,40,20,10])
c = np.array([400,300,600,100,200])
d = np.lexsort((a,b,c))
print('排序後的數組爲:\n',list(zip(a[d],b[d],c[d])))

在這裏插入圖片描述

4.2.2 去重與重複數據

# 數組內數據去重
arr = np.array([1,1,2,3,4,5,5])
print('創建的數組爲:\n',arr)
print('去重後的數組爲:\n',np.unique(arr))
print('去重後的數組爲:\n',sorted(set(arr)))  # 跟np.unique等價的代碼

# 使用tile函數實現數據重複
arr = np.arange(5)
print('創建的數組爲:\n',arr)
print('重複後數組爲:\n',np.tile(arr,3))      # 第二個參數爲重複的次數

# 使用repeat函數實現數據去重
np.random.seed(42)
arr = np.random.randint(0,10,size = (3,3))
print('創建的數組爲:\n',arr)
print('重複後數組爲:\n',arr.repeat(2,axis = 0))  # 按行進行元素重複
print('重複後數組爲:\n',arr.repeat(2,axis = 1))  # 按列進行元素重複

在這裏插入圖片描述

4.2.3 常用的統計函數

# Numpy 中常用統計函數的使用
arr = np.arange(20).reshape(4,5)
print('創建的數組爲:\n',arr)
print('數組的和爲:',np.sum(arr))
print('數組縱軸的和爲:',arr.sum(axis = 0))
print('數組橫軸的和爲:',arr.sum(axis = 1))
print('數組的均值爲:',np.mean(arr))
print('數組縱軸的均值爲:',arr.mean(axis = 0))
print('數組橫軸的均值爲:',arr.mean(axis = 1))
print('數組的標準差爲:',np.std(arr))
print('數組的方差爲:',np.var(arr))
print('數組的最小值爲:',np.min(arr))
print('數組的最大值爲:',np.max(arr))
print('數組的最小值的索引爲:',np.argmin(arr))
print('數組的最大值的索引爲:',np.argmax(arr))

# cumsum函數和cumprod函數的使用
arr = np.arange(2,10)
print('創建的數組爲:',arr)
print('數組元素的累計和爲:',np.cumsum(arr))
print('數組元素的累計積爲:',np.cumprod(arr))

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章