NumPy科學計算庫

写代码的大学生發表於2024-11-03

目錄
  • 第一部分 基本操作
    • 第一節 陣列建立
    • 第二節 檢視操作
      • 1.2.1 陣列的軸數、維度
      • 1.2.2 陣列尺寸形狀
      • 1.2.3 陣列元素的總數
      • 1.2.4 資料型別
      • 1.2.5 陣列中每個元素的大小(以位元組為單位)
    • 第三節 檔案IO操作
      • 1.3.1 儲存陣列
      • 1.3.2 讀取
      • 1.3.3 讀寫csv、txt檔案
  • 第二部分 資料型別
      • array建立時,指定
      • asarray轉換時指定
      • 資料型別轉換astype
  • 第三部分 陣列運算
      • 加減乘除冪運算
      • 邏輯運算
      • 陣列與標量計算
      • *=、+=、-=操作
  • 第四部分 複製和檢視
      • 完全沒有複製
      • 檢視或淺複製
      • 深複製
  • 第五部分 索引、切片和迭代
      • 第一節 基本索引和切片
      • 第二節 花式索引和索引技巧
  • 第六部分 形狀操作
      • 陣列變形
      • 陣列轉置
      • 陣列堆疊
      • split陣列拆分
  • 第七部分 廣播機制
      • 一維陣列廣播
      • 二維陣列的廣播
      • 三維陣列廣播
  • 第八部分 通用函式
      • 第一節 通用函式:元素級數字函式
      • 第二節 where函式
      • 第三節 排序方法
      • 第四節 集合運算函式
      • 第五節 數學和統計函式
  • 第九部分 線性代數
      • 矩陣乘積
      • 矩陣其他計算

NumPy(Numerical Python)是Python的一種開源的數值計算擴充套件。提供多維陣列物件,各種派物件(如掩碼陣列和矩陣),這種工具可用來儲存和處理大型矩陣,比Python自身的巢狀列(nested list structure)結構要高效的多(該結構也可以用來表示矩陣(matrix)),支援大量的維度陣列與矩陣運算,此外也針對陣列運算提供大量的數學函式庫,包括數學、邏輯、形狀操作、排序、選擇、輸入輸出、離散傅立葉變換、基本線性代數,基本統計運算和隨機模擬等等。

  • 幾乎所有從事Python工作的資料分析師都利用NumPy的強大功能。

    • 強大的N維陣列
    • 成熟的廣播功能
    • 用於整合C/C++和Fortran程式碼的工具包
    • NumPy提供了全面的數學功能、隨機數生成器和線性代數功能
  • 安裝Python庫

  • 第一種方式:

    • pip install jupyter -i https://pypi.tuna.tsinghua.edu.cn/simple
    • pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 第二種方式:

    • 直接安裝anaconda下載

第一部分 基本操作

第一節 陣列建立

建立陣列的最簡單的方法就是使用array函式,將Python下的list轉換為ndarray。

import numpy as np
l = [1,3,5,7,9] # 列表
arr = np.array(l) # 將列表轉換為NumPy陣列
arr # 資料一樣,NumPy陣列的方法,功能更加強大
# 輸出為
# array([1, 3, 5, 7, 9])

我們可以利用np中的一些內建函式來建立陣列,比如我們建立全0的陣列,也可以建立全1陣列,全是其他數字的陣列,或者等差數列陣列,正態分佈陣列,隨機數。

import numpy as np
arr1 = np.ones(10) # 輸出為:array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
arr2 = np.zeros(10) # 輸出為: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
arr3 = np.full(shape = [2,3],fill_value=2.718) 
# 輸出為:
# array([[2.718, 2.718, 2.718],
#       [2.718, 2.718, 2.718]])
arr4 = np.arange(start = 0,stop = 20,step = 2) 
# 等差數列 輸出為:array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])
arr5 = np.linspace(start =0,stop = 9,num = 10) 
# 等差數列 輸出為:array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
arr6 = np.random.randint(0,100,size = 10) 
# int隨機數 輸出為:array([ 4,  8, 79, 62, 34, 35,  2, 65, 47, 18])
arr7 = np.random.randn(5) 
# 正態分佈 輸出為:array([ 0.57807872,  0.37922855,  2.37936837, -0.28688769,  0.2882854 ])
arr8 = np.random.random(size = 5) 
# float 隨機數 輸出為:array([0.59646412, 0.37960586, 0.38077327, 0.76983539, 0.22689201])

第二節 檢視操作

  • jupyter擴充套件外掛(不安裝)
    • pip install jupyter_contrib_nbextensions -i https://pypi.tuna.tsinghua.edu.cn/simple
    • pip install jupyter_nbextensions_configurator -i https://pypi.tuna.tsinghua.edu.cn/simple
    • jupyter contrib nbextension install --user
    • jupyter nbextensions_configurator enable --user
    • 退出,重新進入jupyter notebook就可以了

NumPy的陣列類稱為ndarray,也被稱為別名 array。請注意,numpy.array這與標準Python庫類不同array.array,後者僅處理一維陣列且功能較少。ndarray物件的重要屬性是

1.2.1 陣列的軸數、維度

import numpy as np 
arr = np.random.randint(0,100,size = (3,4,5))
arr.ndim # 輸出 3

1.2.2 陣列尺寸形狀

import numpy as np 
arr = np.random.randint(0,100,size = (3,4,5))
arr.shape # 輸出 (3,4,5)

1.2.3 陣列元素的總數

import numpy as np 
arr = np.random.randint(0,100,size = (3,4,5))
arr.size # 輸出 3*4*5 = 60

1.2.4 資料型別

import numpy as np 
arr = np.random.randint(0,100,size = (3,4,5))
arr.dtype # 輸出 dtype('int64')

1.2.5 陣列中每個元素的大小(以位元組為單位)

import numpy as np 
arr = np.random.randint(0,100,size = (3,4,5))
arr.itemsize #輸出是 8 ,因為資料型別是int64,64位,一個位元組是8位,所以64/8 = 8

第三節 檔案IO操作

1.3.1 儲存陣列

save方法儲存ndarray到一個npy檔案,也可以使用savez將多個array儲存到一個.npz檔案中

x = np.random.randn(5)
y = np.arange(0,10,1)
#save方法可以存一個ndarray
np.save("x_arr",x)
#如果要存多個陣列,要是用savez方法,儲存時以key-value形式儲存,key任意(xarr、yarr)
np.savez("some_array.npz",xarr = x,yarr=y)

1.3.2 讀取

load方法來讀取儲存的陣列,如果是.npz檔案的話,讀取之後相當於形成了一個key-value型別的變數,透過儲存時定義的key來獲取相應的array

np.load('x_arr.npy') # 直接載入

# 透過key獲取儲存的陣列資料
np.load('some_array.npz')['yarr']

1.3.3 讀寫csv、txt檔案

arr = np.random.randint(0,10,size = (3,4))
#儲存陣列到txt檔案
np.savetxt("arr.csv",arr,delimiter=',') # 檔案字尾是txt也是一樣的
#讀取txt檔案,delimiter為分隔符,dtype為資料型別
np.loadtxt("arr.csv",delimiter=',',dtype=np.int32)

第二部分 資料型別

ndarray的資料型別:

  • int: int8、uint8、int16、int32、int64
  • float: float16、float32、float64
  • str

array建立時,指定

import numpy as np
np.array([1,2,5,8,2],dtype = 'float32') 
# 輸出 :array([1., 2., 5., 8., 2.], dtype=float32)

asarray轉換時指定

import numpy as np
arr = [1,3,5,7,2,9,0]
# asarray 將列表進行變換
np.asarray(arr,dtype = 'float32') 
# 輸出:array([1., 3., 5., 7., 2., 9., 0.], dtype=float32)

資料型別轉換astype

import numpy as np
arr = np.random.randint(0,10,size = 5,dtype = 'int16') 
# 輸出:array([6, 6, 6, 6, 3], dtype=int16)
# 使用astype進行轉換
arr.astype('float32') # 輸出:array([1., 4., 0., 6., 6.], dtype=float32)

第三部分 陣列運算

加減乘除冪運算

import numpy as np
arr1 = np.array([1,2,3,4,5])
arr2 = np.array([2,3,1,5,9])
arr1 - arr2 # 減法
arr1 * arr2 # 乘法
arr1 / arr2 # 除法
arr1**arr2 # 兩個星號表示冪運算

邏輯運算

import numpy as np
arr1 = np.array([1,2,3,4,5])
arr2 = np.array([1,0,2,3,5])
arr1 < 5
arr1 >= 5
arr1 == 5
arr1 == arr2
arr1 > arr2

陣列與標量計算

陣列與標量的算術運算也會將標量值傳播到各個元素

import numpy as np
arr = np.arange(1,10)
1/arr
arr+5
arr*5

*=、+=、-=操作

某些操作(例如+=和*=)只會修改現有陣列,而不是建立一個新陣列。

import numpy as np
arr1 = np.arange(5)
arr1 +=5
arr1 -=5
arr1 *=5
# arr1 /=5 不支援運算

第四部分 複製和檢視

在運算元組時,有時會將其資料複製到新陣列中,有時不復制。

對於初學者來說,這通常會引起混亂。有以下三種情況

完全沒有複製

import numpy as np
a = np.random.randint(0,100,size = (4,5))
b = a
a is b # 返回True a和b是兩個不同名字對應同一個記憶體物件
b[0,0] = 1024 # 命運共同體
display(a,b)

檢視或淺複製

不同的陣列物件可以共享相同的資料。該view方法建立一個檢視相同資料的新陣列物件

import numpy as np
a = np.random.randint(0,100,size = (4,5))
b = a.view() # 使用a中的資料建立一個新陣列物件
a is b # 返回False a和b是兩個不同名字對應同一個記憶體物件
b.base is a # 返回True,b檢視的根資料和a一樣
b.flags.owndata # 返回False b中的資料不是其自己的
a.flags.owndata # 返回True a中的資料是其自己的
b[0,0] = 1024 # a和b的資料都發生改變
display(a,b)

深複製

import numpy as np
a = np.random.randint(0,100,size = (4,5))
b = a.copy()
b is a # 返回False
b.base is a # 返回False
b.flags.owndata # 返回True
a.flags.owndata # 返回True
b[0,0] = 1024 # b改變,a不變,分道揚鑣
display(a,b)
  • copy應該在不再需要原來的陣列情況下,切片後呼叫。例如,假設a是一個巨大的中間結果,而最終結果b僅包含的一小部分a,則在b使用切片進行構造時應制作一個深複製:

    import numpy as np
    a = np.arange(1e8)
    b = a[::1000000].copy() # 每100萬個資料中取一個資料
    del a # 不在需要a,刪除佔大記憶體的a
    b.shape # shape(100,)
    

第五部分 索引、切片和迭代

第一節 基本索引和切片

numpy中陣列切片是原始陣列的檢視,這意味著資料不會被複制,檢視上任何資料的修改都會反映到原陣列上

arr = np.array([0,1,2,3,4,5,6,7,8,9])
arr[5] #索引 輸出 5
arr[5:8] #切片輸出:array([5, 6, 7])
arr[2::2] # 從索引2開始每兩個中取一個 輸出 array([2, 4, 6, 8])
arr[::3] # 不寫索引預設從0開始,每3箇中取一個 輸出為 array([0, 3, 6, 9])
arr[1:7:2] # 從索引1開始到索引7結束,左閉右開,每2個數中取一個 輸出 array([1, 3, 5])
arr[::-1] # 倒序 輸出 array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
arr[::-2] # 倒序 每兩個取一個 輸出  array([9, 7, 5, 3, 1])
arr[5:8]=12 # 切片賦值會賦值到每個元素上,與列表操作不同
temp = arr[5:8]
temp[1] = 1024
arr # 輸出:array([   0,    1,    2,    3,    4,   12, 1024,   12,    8,    9])

對於二維陣列或者高維陣列,我們可以按照之前的知識來索引,當然也可以傳入一個以逗號隔開的索引列表來選區單個或多個元素

arr2d = np.array([[1,3,5],[2,4,6],[-2,-7,-9],[6,6,6]]) # 二維陣列 shape(3,4)
arr2d[0,-1] #索引 等於arr2d[0][-1] 輸出 5
arr2d[0,2]  #索引 等於arr2d[0][2] ==  arr2d[0][-1] 輸出 5

arr2d[:2,-2:] #切片 第一維和第二維都進行切片 等於arr2d[:2][:,1:] 
arr2d[:2,1:] #切片 1 == -2 一個是正序,另個一是倒序,對應相同的位置
# 輸出:
#array([[3, 5],
#       [4, 6]])

第二節 花式索引和索引技巧

  • 整數陣列進行索引即花式索引,其和切片不一樣,它總是將資料複製到新陣列中
import numpy as np
#一維
arr1 = np.array([1,2,3,4,5,6,7,8,9,10])
arr2 = arr1[[1,3,3,5,7,7,7]] # 輸出 array([2, 4, 4, 6, 8, 8, 8])
arr2[-1] = 1024 # 修改值,不影響arr1
#二維
arr2d = np.array([[1,3,5,7,9],[2,4,6,8,10],[12,18,22,23,37],[123,55,17,88,103]]) #shape(4,5)
arr2d[[1,3]] # 獲取第二行和第四行,索引從0開始的所以1對應第二行 
# 輸出 array([[  2,   4,   6,   8,  10],
#            [123,  55,  17,  88, 103]])
arr2d[([1,3],[2,4])] # 相當於arr2d[1,2]獲取一個元素,arr2d[3,4]獲取另一個元素
# 輸出為 array([  6, 103])
# 選擇一個區域
arr2d[np.ix_([1,3,3,3],[2,4,4])] # 相當於 arr2d[[1,3,3,3]][:,[2,4,4]]
arr2d[[1,3,3,3]][:,[2,4,4]]
# ix_()函式可用於組合不同的向量
# 第一個列表存的是待提取元素的行標,第二個列表存的是待提取元素的列標
# 輸出為
# array([[  6,  10,  10],
#        [ 17, 103, 103],
#        [ 17, 103, 103],
#        [ 17, 103, 103]])
  • boolean值索引
names = np.array(['softpo','Brandon','Will','Michael','Will','Ella','Daniel','softpo','Will','Brandon'])
cond1 = names == 'Will'
cond1 
# 輸出array([False, False,  True, False,  True, False, False, False,  True, False])
names[cond1] # array(['Will', 'Will', 'Will'], dtype='<U7')
arr = np.random.randint(0,100,size = (10,8)) # 0~100隨機數
cond2 = arr > 90 
# 找到所有大於90的索引,返回boolean型別的陣列 shape(10,8),大於返回True,否則False
arr[cond2] # 返回資料全部是大於90的

第六部分 形狀操作

陣列變形

import numpy as np
arr1 = np.random.randint(0,10,size = (3,4,5))
arr2 = arr1.reshape(12,5) # 形狀改變,返回新陣列
arr3 = arr1.reshape(-1,5) # 自動“整形”,自動計算

陣列轉置

import numpy as np
arr1 = np.random.randint(0,10,size = (3,5)) # shape(3,5)
arr1.T # shape(5,3) 轉置
arr2 = np.random.randint(0,10,size = (3,6,4)) # shape(3,6,4)
np.transpose(arr2,axes=(2,0,1)) # transpose改變陣列維度 shape(4,3,6)

陣列堆疊

import numpy as np
arr1 = np.array([[1,2,3]])
arr2 = np.array([[4,5,6]])
np.concatenate([arr1,arr2],axis = 0) 
# 串聯合並shape(2,3) axis = 0表示第一維串聯 輸出為
# array([[1, 2, 3],
#        [4, 5, 6]])
np.concatenate([arr1,arr2],axis = 1) 
# shape(1,6) axis = 1表示第二維串聯 輸出為:array([[1, 2, 3, 4, 5, 6]])

np.hstack((arr1,arr2)) # 水平方向堆疊 輸出為:array([[1, 2, 3, 4, 5, 6]])
np.vstack((arr1,arr2)) 
# 豎直方向堆疊,輸出為:
# array([[1, 2, 3],
#        [4, 5, 6]])

split陣列拆分

import numpy as np
arr = np.random.randint(0,10,size = (6,5)) # shape(6,5)
np.split(arr,indices_or_sections=2,axis = 0) # 在第一維(6)平均分成兩份 
np.split(arr,indices_or_sections=[2,3],axis = 1) # 在第二維(5)以索引2,3為斷點分割成3份

np.vsplit(arr,indices_or_sections=3) # 在豎直方向平均分割成3份
np.hsplit(arr,indices_or_sections=[1,4]) # 在水平方向,以索引1,4為斷點分割成3份

第七部分 廣播機制

當兩個陣列的形狀並不相同的時候,我們可以透過擴充套件陣列的方法來實現相加、相減、相乘等操作,這種機制叫做廣播(broadcasting)

一維陣列廣播

import numpy as np
arr1 = np.sort(np.array([0,1,2,3]*3)).reshape(4,3) #shape(4,3)
arr2 = np.array([1,2,3]) # shape(3,)
arr3 = arr1 + arr2 # arr2進行廣播複製4份 shape(4,3)
arr3

二維陣列的廣播

import numpy as np
arr1 = np.sort(np.array([0,1,2,3]*3)).reshape(4,3) # shape(4,3)
arr2 = np.array([[1],[2],[3],[4]]) # shape(4,1)
arr3 = arr1 + arr2 # arr2 進行廣播複製3份 shape(4,3)
arr3

三維陣列廣播

import numpy as np
arr1 = np.array([0,1,2,3,4,5,6,7]*3).reshape(3,4,2) #shape(3,4,2)
arr2 = np.array([0,1,2,3,4,5,6,7]).reshape(4,2) #shape(4,2)
arr3 = arr1 + arr2 # arr2陣列在0維上覆制3份 shape(3,4,2)
arr3

第八部分 通用函式

第一節 通用函式:元素級數字函式

abs、sqrt、square、exp、log、sin、cos、tan,maxinmum、minimum、all、any、inner、clip、round、trace、ceil、floor

import numpy as np
arr1 = np.array([1,4,8,9,16,25])
np.sqrt(arr1) # 開平方
np.square(arr1) # 平方
np.clip(arr1,2,16) # 輸出 array([ 2,  4,  8,  9, 16, 16])

x = np.array([1,5,2,9,3,6,8])
y = np.array([2,4,3,7,1,9,0])
np.maximum(x,y) # 返回兩個陣列中的比較大的值
arr2 = np.random.randint(0,10,size = (5,5))
np.inner(arr2[0],arr2) #返回一維陣列向量內積

第二節 where函式

where 函式,三個引數,條件為真時選擇值的陣列,條件為假時選擇值的陣列

import numpy as np
arr1 = np.array([1,3,5,7,9])
arr2 = np.array([2,4,6,8,10])
cond = np.array([True,False,True,True,False])
np.where(cond,arr1,arr2) # True選擇arr1,False選擇arr2的值
# 輸出 array([ 1,  4,  5,  7, 10])

arr3 = np.random.randint(0,30,size = 20)
np.where(arr3 < 15,arr3,-15) # 小於15還是自身的值,大於15設定成-15

第三節 排序方法

np中還提供了排序方法,排序方法是就地排序,即直接改變原陣列

arr.sort()、np.sort()、arr.argsort()

import numpy as np
arr = np.array([9,3,11,6,17,5,4,15,1])
arr.sort() # 直接改變原陣列
np.sort(arr) # 返回深複製排序結果
arr = np.array([9,3,11,6,17,5,4,15,1])
arr.argsort() # 返回從小到大排序索引 array([8, 1, 6, 5, 3, 0, 2, 7, 4])

第四節 集合運算函式

A = np.array([2,4,6,8])
B = np.array([3,4,5,6])
np.intersect1d(A,B) # 交集 array([4, 6])
np.union1d(A,B) # 並集 array([2, 3, 4, 5, 6, 8])
np.setdiff1d(A,B) #差集,A中有,B中沒有 array([2, 8])

第五節 數學和統計函式

min、max、mean、median、sum、std、var、cumsum、cumprod、argmin、argmax、argwhere、cov、corrcoef

import numpy as np
arr1 = np.array([1,7,2,19,23,0,88,11,6,11])
arr1.min() # 計算最小值 0
arr1.argmax() # 計算最大值的索引 返回 6
np.argwhere(arr1 > 20) # 返回大於20的元素的索引
np.cumsum(arr1) # 計算累加和
arr2 = np.random.randint(0,10,size = (4,5))
arr2.mean(axis = 0) # 計算列的平均值
arr2.mean(axis = 1) # 計算行的平均值
np.cov(arr2,rowvar=True) # 協方差矩陣
np.corrcoef(arr2,rowvar=True) # 相關性係數

第九部分 線性代數

矩陣乘積

#矩陣的乘積
A = np.array([[4,2,3],
              [1,3,1]]) # shape(2,3)
B = np.array([[2,7],
              [-5,-7],
              [9,3]]) # shape(3,2)
np.dot(A,B) # 矩陣運算 A的最後一維和B的第一維必須一致
A @ B # 符號 @ 表示矩陣乘積運算

矩陣其他計算

下面可以計算矩陣的逆、行列式、特徵值和特徵向量、qr分解值,svd分解值

#計算矩陣的逆
from numpy.linalg import inv,det,eig,qr,svd
A = np.array([[1,2,3],
              [2,3,4],
              [4,5,8]]) # shape(3,3)
inv(t) # 逆矩陣
det(t)#計算矩陣行列式

相關文章