Numpy之ndarray基礎篇


NumPy(Numerical Python) 是 Python 語言的一個擴展程序庫,支持大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫。是在學習機器學習、深度學習之前應該掌握的一個非常基本且實用的Python庫。

Numpy官方文檔

初見ndarray對象

ndarray基本概念

ndarray是numpy庫中的一個處於核心地位的數據結構,全稱爲N-Dimension Array,從字面上就表明了它是一個N維數組。要注意的是,ndarray是同質的,就是說其中的元素都必須是同一種數據類型(PS: python中的list列表是異質的)
ndarray實例化後,包含一些基本屬性,如shape、ndim、size、dtype等。例如現在有一個3行5列的矩陣(ndarray)如下:

array([[ 0,  1,  2,  3,  4],
	   [ 5,  6,  7,  8,  9],
	   [10, 11, 12, 13, 14]])

那麼該ndarray的shape值爲(3,5)(元組類型,表示3行5列)
ndim爲2(表示矩陣維度爲2)
size爲15(矩陣總共有15個元素)
dtype爲int32(因爲矩陣中的元素都是32位整數)

# 導入numpy並取別名爲np
import numpy as np
# 構造ndarray
a = np.arange(15).reshape(3, 5)
# 打印a的shape,ndim,size,dtype
print(a.shape)
print(a.ndim)
print(a.size)
print(a.dtype)

ndarray對象實例化的方法

實例化ndarray的最常用的方法就是使用array函數,用list對象作爲參數傳遞,返回以list中的內容爲初始值的ndarray對象:

import numpy as np
# 使用列表作爲初始值,實例化ndarray對象a
a = np.array([2,3,4])
# 打印ndarray對象a
print(a)

在這裏插入圖片描述
除了array以外比較常用的實例化函數還有zeros、ones、empty,這三個函數的參數都是表示返回ndarray對象形狀的元組

zeros返回一個全爲0的ndarray對象:

import numpy as np
# 實例化ndarray對象a,a是一個3行4列的矩陣,矩陣中元素全爲0
a = np.zeros((3, 4))
# 打印ndarray對象a
print(a)

在這裏插入圖片描述
ones與上類似,返回一個全爲1的ndarray對象:

import numpy as np
# 實例化ndarray對象a,a是一個3行4列的矩陣,矩陣中元素全爲1
a = np.ones((3, 4))
# 打印ndarray對象a
print(a)

在這裏插入圖片描述
empty則是返回一個元素的值沒有經過初始化的ndarray:

import numpy as np
# 實例化ndarray對象a,a是一個2行3列的矩陣,矩陣中元素全爲隨機值
a = np.empty((2, 3)) 
# 打印ndarray對象a
print(a)

在這裏插入圖片描述

ndarray形狀操作

ndarray的數組與一般的數組列表的一個不同之處就是它可以變換形狀,這使得一些數據處理的操作變得尤爲方便。最直接粗暴的變換方法就是修改shape屬性的值

import numpy as np
a = np.zeros((3, 4))
# 直接修改shape屬性
a.shape = [4, 3]

在這裏插入圖片描述
但這樣做不符合編程規範,更優雅的方法是使用ndarray對象提供的方法reshape。該方法(及其他大部分方法都)有兩種調用方式,一種是直接作爲函數調用,參數爲ndarray對象及形狀元組;另一種是作爲ndarray實例的成員函數來調用。

面向對象風格

import numpy as np
a = np.zeros((3, 4))
# 調用a的成員函數reshape將3行4列改成4行3列
a = a.reshape((4, 3))

面向過程風格

import numpy as np
a = np.zeros((3, 4))
# 調用reshape函數將a變形成4行3列
a = np.reshape(a, (4, 3))

另外,reshape有一個非常方便的功能就是可以自動判斷某一維上的長度。例如要將一個6行8列的二維數組變化成2列,那麼只要在未知的維上傳入參數-1,reshape就會自動得出變化後的數組應爲24行

import numpy as np
a = np.zeros((6, 8))
# 行的維度上填-1,會讓numpy自己去推算出行的數量,很明顯,行的數量應該是24
a = a.reshape((-1, 2))

在這裏插入圖片描述
不過最多隻有一個維度能填-1,如果超過一個維度是-1就會拋出異常
在這裏插入圖片描述

PS:要注意reshape並不會改變原ndarray的形狀,而只是返回變化後的ndarray對象,所以需要將其賦值給原變量。

如果想要直接改變原ndarray的形狀,除了之前的直接修改shape屬性,可以使用resize方法:

import numpy as np
a = np.zeros((3, 4))
# 將a從3行4列的二維數組變成一個有12個元素的一維數組
a.resize(12)

ndarray基礎操作

作爲數據處理的利器,ndarray自然提供了常用的數學的處理功能。

基本運算

ndarray可以直接和基本的數字類型變量運算,返回該運算作用到數組中所有元素上的結果。

import numpy as np
a = np.array([0, 1, 2, 3])
# a中的所有元素都加2,結果爲[2, 3, 4, 5]
b = a + 2
# a中的所有元素都減2,結果爲[-2, -1, 0, 1]
c = a - 2
# a中的所有元素都乘以2,結果爲[0, 2, 4, 6]
d = a * 2
# a中的所有元素都平方,結果爲[0, 1, 4, 9]
e = a ** 2
# a中的所有元素都除以2,結果爲[0, 0.5, 1, 1.5]
f = a / 2
# a中的所有元素都與2比,結果爲[True, True, False, False]
g = a < 2

ndarray與ndarray之間也可以運算,返回兩個數組中對應位置元素相互作用的結果。

import numpy as np
a = np.array([[0, 1], [2, 3]])
b = np.array([[1, 1], [3, 2]])
# a與b逐個元素相加,結果爲[[1, 2], [5, 5]]
c = a + b
# a與b逐個元素相減,結果爲[[-1, 0], [-1, 1]]
d = a - b
# a與b逐個元素相乘,結果爲[[0, 1], [6, 6]]
e = a * b
# a的逐個元素除以b的逐個元素,結果爲[[0., 1.], [0.66666667, 1.5]]
f = a / b
# a與b逐個元素做冪運算,結果爲[[0, 1], [8, 9]]
g = a ** b
# a與b逐個元素相比較,結果爲[[True, False], [True, False]]
h = a < b

PS:當運算的兩個ndarray形狀不同時,會觸發Numpy的廣播(broadcasting)機制嘗試將兩個ndarray自動拓展成相同形狀。關於廣播機制將在下一篇文章中講解。

上述運算都是逐個元素進行運算,如果想要進行數學中的矩陣乘這種運算,可以使用Numpy提供的運算符@或函數dot。

import numpy as np
A = np.array([[1, 1], [0, 1]])
B = np.array([[2, 0], [3, 4]])
# @表示矩陣乘法,矩陣A乘以矩陣B,結果爲[[5, 4], [3, 4]]
print(A @ B)
# 面向對象風格,矩陣A乘以矩陣B,結果爲[[5, 4], [3, 4]]
print(A.dot(B))
# 面向過程風格,矩陣A乘以矩陣B,結果爲[[5, 4], [3, 4]]
print(np.dot(A, B))

簡單統計

在一般的數組中進行統計需要手動用循環遍歷整個數組,而ndarray爲了解放程序員們的雙手,提供了sum、min、max、argmax、argmin等方法實現簡單的統計功能。

import numpy as np
a = np.array([[-1, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 13]])
# 計算a中所有元素的和,結果爲67
print(a.sum())
# 找出a中最大的元素,結果爲13
print(a.max())
# 找出a中最小的元素,結果爲-1
print(a.min())
# 找出a中最大元素在a中的位置,由於a中有12個元素,位置從0開始計,所以結果爲11
print(a.argmax())
# 找出a中最小元素在a中位置,結果爲0
print(a.argmin())

當需要按某一個方向/軸來進行統計時,可以向這些方法傳入axis參數。例如有一個學生成績表如下,要統計出每一名學生的總分:

姓名 語文 數學 英語 物理 化學 政治 歷史
張三 90 112 104 84 89 77 80
李四 105 109 114 81 81 87 92
王五 93 103 97 79 75 80 79

用ndarray存儲如下

a=np.array([[  90, 112, 104,  84,  89,  77,  80],
			[ 105, 109, 114,  81,  81,  87,  92],
			[  93, 103,  97,  79,  75,  80,  79]])

那麼要做的就是統計每一行的和,沿着橫軸把元素相加,axis爲所沿軸的序號
在這裏插入圖片描述
在這裏插入圖片描述
其餘方法以及更高維的數組同理。

PS:當沒有修改axis時,axis的值默認爲None。意思是在統計時會把ndarray對象中所有的元素都考慮在內。

隨機數生成

簡單隨機數生成

NumPy的random模塊下提供了許多生成隨機數的函數,如果對於隨機數的概率分佈沒有什麼要求,則通常可以使用random_sample、choice、randint等函數來實現生成隨機數的功能。這些函數的功能都和Python標準庫random 中的類似,只不過是作用在ndarray對象上或返回ndarray。

random_sample:用於生成區間爲[0,1][0,1]的隨機數,參數size爲生成ndarray的形狀。

import numpy as np
'''
結果可能爲[[0.32343809, 0.38736262, 0.42413616]
          [0.86190206, 0.27183736, 0.12824812]]
'''
print(np.random.random_sample(size=[2, 3]))

choice:從給定範圍的數字中隨機挑選生成ndarray。參數a是一維數組或整數,給定一維數組時生成ndarray中的元素將從中隨機選取,給定整數時則從np.arange(a)中隨機選取;參數size爲生成ndarray形狀;參數replace決定是否能有重複元素,默認值爲True即允許重複。

import numpy as np
'''
模擬擲5次骰子
擲骰子時可能出現的點數爲1, 2, 3, 4, 5, 6,所以a=[1,2,3,4,5,6]
模擬5次擲骰子所以size=5
骰子點數可以重複出現所以replace=True
結果可能爲 [4 3 1 4 3]
'''
print(np.random.choice(a=[1, 2, 3, 4, 5, 6], size=5,replace=True))

PS:當生成ndarray中元素數量多於a且replace=False時會拋出異常ValueError: Cannot take a larger sample than population when ‘replace=False’

randint:生成選定區間內的整數隨機選取產生的ndarray。參數low、high爲區間的上下限,區間爲半開半閉區間[low,high)[low,high);參數size爲生成數組形狀。

import numpy as np
'''
模擬擲5次骰子
擲骰子時可能出現的點數爲1, 2, 3, 4, 5, 6,所以low=1,high=7
模擬5此擲骰子所以size=5
結果可能爲 [6, 4, 3, 1, 3]
'''
print(np.random.randint(low=1, high=7, size=5)

概率分佈隨機數生成

如果對於產生的隨機數的概率分佈有特別要求,NumPy同樣提供了從指定的概率分佈中採樣得到的隨機值的接口。在這裏主要介紹正態分佈。
正態分佈又稱爲高斯分佈,其分佈圖形如下:
在這裏插入圖片描述
要根據正態分佈產生隨機數,可以使用normal函數。該函數的參數有loc、scale、size,分別是正態分佈的均值、方差和生成數組的形狀。默認情況下loc=0,scale=1,即標準正態分佈。
在這裏插入圖片描述

隨機種子

衆所周知計算機無法產生真正的隨機數,所有計算機產生的隨機數本質都是僞隨機數,其結果由隨機種子決定。Numpy中手動設定隨機種子的方法就是使用seed函數,其參數爲seed。

import numpy as np
# 設置隨機種子爲233
np.random.seed(seed=233)
data = [1, 2, 3, 4]
# 隨機從data中挑選數字,結果爲4
print(np.random.choice(data))
# 隨機從data中挑選數字,結果爲4
print(np.random.choice(data))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章