L:python的Numpy模塊(存取數組元素,數組運算,排序,隨機函數)

簡介

NumPy(Numerical Python)是一個開源Python科學計算庫,是Python生態圈最重要的底層支持庫,支持快速的數組運算,比純Python代碼快得多,因爲它底層使用到c來寫。NumPy是在Python中進行數據分析、機器學習、人工智能開發的必備工具,是理解學習很多Python工具包的基礎。
安裝 : pip install numpy # Anaconda已包含np,無需安裝。

numpy數組和 list列表運算時間對比示例
import  numpy  as  np			# 引入慣例, 後續都用  np
lst = list(range(1000000))		# 列表
ar = np.arange(1000000)		# np數組
In: %timeit   lst2 = [x*2  for  x  in  lst]
80.8 ms ± 438 µs per loop		# 列表耗時
In: %timeit   ar2 = ar * 2
1.96 ms ± 34.7 µs per loop		# np數組耗時
注:%魔術命令只能在IPython對話窗口運行,不能放入.py程序中。

數組對象特性

x = np.array((90, 85, 80))     	# 成績
w = np.array((0.4, 0.4, 0.2))  	# 權重
np.mean(x)	#求平均值
np.average(x, weights=w)  	# 按權重求均值
np.sum(x * w) / np.sum(w) 	# 自行按權重求均值,(x*w)會對應的元素相乘

In: b = np.array((10, 9.5, 10.2, 11, 10.8, 10.6, 11.2))   # 收盤價 
In: np.diff(b)   			# 差值,   也可寫爲   b[1:]  -  b[:-1] ,這樣寫就是後面一個元素減去前面一個元素
Out: array([-0.5,  0.7,  0.8, -0.2, -0.2,  0.6])
In: ret = np.diff(b) / b[:-1]   	# 漲跌率
Out: array([-0.05,  0.07,  0.08, -0.02, -0.02,  0.06])
In: np.where(ret>0)		# 正收益是哪幾天
Out:(array([1, 2, 5], dtype=int64),) 
In: np.__version__     # 版本號'1.16.5',一般的軟件包都有
# arange產生6個數,reshape重設爲 2x3 數組
In: b = np.arange(6).reshape(2, 3)
In: type(b)  	#  numpy.ndarray
# 數組對象的各種特性
In: b.ndim     	# 數組維度  2
In: b.size       	# 數組中的元素個數 6,   和len(b) 不同,len(b)顯示的是數組行數
In: b.shape   	# 數組形狀 (2, 3)
In: b.dtype    	# 數組元素的數據類型  dtype('int32')
In: b.itemsize	# 單個元素所需存儲字節數  4
In: b.nbytes	# 整個數組所需存儲字節數 24  , 即 size * itemsize

生成數組的五種方法

#使用array()/arange()生成數組
In:b = np.array((1, 2, 3, 4)) # 一維
Out: array([1, 2, 3, 4])
In:b = np.arange(1, 5)   	# np.arange(1,5,0.5) 小數步長
Out: array([1, 2, 3, 4])
In: np.repeat(b,2)    	# 將元素重複2次
Out:array([1, 1, 2, 2, 3, 3, 4, 4])
In: np.tile(b, 3)  		# 將數組重複3次
Out: array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4])
In:b = np.array([[1, 2] , [3, 4], [5, 6]])       # 二維
In:b=np.arange(4000).reshape(4, 1000) # 二維
#可以使用ones()/zeros()/linspace()生成數組。
np.ones(5) 		# 生成含有5個元素的一維全1數組
np.ones((2, 3))    	# 生成2x3的二維全1數組
np.zeros((2, 3)) 	# 生成2x3的二維全0數組
np.ones_like(b)      	# 生成維數和b相同的全1數組
np.eye(3) 		# 單位矩陣數組

np.linspace(1, 2, 5)  			# [1, 2] 間均勻分佈5個數
Out: array([1.  , 1.25, 1.5 , 1.75, 2.  ]) 	# 默認含終值
np.linspace(1, 2, 5, endpoint=False)   	# 不含終值
Out:array([1. , 1.2, 1.4, 1.6, 1.8])

x = np.linspace(0, np.pi, 7)  # [0, π] 間均勻分佈7個數, 即間隔 30度
np.sin(x)    	#  np.round(np.sin(x), 2)
#使用隨機函數生成數組。
ar = np.random.rand(3,4) 		# 3x4數組, [0, 1)內均勻分佈小數
np.set_printoptions(precision=3)   	# 小數部分顯示3位

np.random.randint(1,100,5)  		# [1,100)內5個隨機整數
np.random.randint(1,100,(2,3))  	# 2x3 數組

np.random.randn(10,20) 		# 10x20的標準正太 N(0,1)數組
# 符合正太分佈N(1, 4) 的 3x4 數組
x = np.random.normal(loc=1, scale=2, size=(3, 4))
x.std() ,  x.var()  ,   x.mean()   		# 標準差,   方差,   均值

NumPy的常用數據類型
在這裏插入圖片描述

在創建數組時可以用dtype參數指定數據類型。已有的數組可以用astype()方法轉換類型。數組元素的類型一般應相同,列表的元素類型允許不同。

In:b=np.arange(5)  		# 默認 'int32' 類型
In: b.dtype
Out: dtype('int32')
In: b[0] = 2**40			# 將報錯,整數超範圍

In:b=np.arange(5, dtype='float')  #  指定爲 'float'
In: b.dtype
Out: dtype('float64')

In: c=b.astype('int')             	# 轉爲int,b不變,得到新的c
In: c.dtype
Out: dtype('int32')

In: c.astype('bool')		# 轉爲bool型,非0對應True
Out: array([False,  True,  True,  True,  True])

存取數組元素

基本索引和切片操作
np數組可按類似列表訪問的語法,單個索引或切片訪問。

b=np.arange(5,10)    		# array([5,6,7,8,9])
b[1],  b[-1],    b[:2], b[1:3]      	# (6, 9, array([5, 6]), array([6, 7]))
b[[0,1,3]]   			# 花式索引 array([5,6,8]),  這裏的索引結果是複製
重要:數組切片和列表切片不同,前者是視圖,後者是複製。
b=np.arange(5,10)    	# array([5,6,7,8,9])
c=b[0:3]       		# 產生視圖,b,c指向同一內存塊
c[0]=100     		# 此修改將同時影響 b 和 c
c  			# array([100,6,7])
b           		# array([100,6,7,8,9])
c = b[0:3].copy()  	# 複製數組,這樣 b, c分離,不會再互相影響

二維數組

b=np.arange(12).reshape(3,4)
Out:array([[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7],
                  [ 8,  9, 10, 11]])  
b[1, 2]  		# 6,也可寫爲  b[1][2] 
b[1, 1:3]    	# array([5,6])
b[1]   		# array([4,5,6,7])
b[:,1]          	# array([1,5,9])
b[1:3, 1:4]   	# array([5,6,7],
                        [9,10,11])
b[ [0,1,2], [3,2,1] ]  # array([3, 6, 9]),  將行/列座標分別排列,花式索引,花式索引是複製操作

布爾索引
篩選出True值對應位置的數據。

np.random.seed(7)
b = np.random.randint(40, 100, size=10) 	# 生成10個的隨機整數
Out: array([87, 44, 65, 94, 43, 59, 63, 79, 68, 97])
c = b < 60            				# 生成一個布爾數組c
Out: array([False, True, False, False, True, True, False, False, False, False])
b[c]          		# 利用布爾索引取數據,得到<60的數據
Out: array([44, 43, 59])

b[(b>=60) & (b<=80)]   	# 顯示60~80間的數據, 此處用&, 不能用and
b[(b<60) | (b>90)]        	# 顯示<60  或 >90的數據,此處用|, 不能用or
b[~(b<60)]		# ~非, 顯示 >=60的數據
b=np.array((60, 70, 75, 90, 68, 89))	# 成績
c=np.array((1 ,  1 ,  1,    2 ,  2,  2))	# 班級
b[c==1].mean()				#  1班平均成績
x=np.array((70, 75, 92, 68, 89))	# 評分1
y=np.array((75, 69, 93, 70, 85))	# 評分2
np.where(x>y, x, y)			# 取x/y兩兩比較的較大值
#where函數是當x>y時取x,不然取y,作用效果和np.maximum(x,y)一樣
np.where(x>y, 1, 0)			# x>y則取1, 否則取0  

數組運算

數組和單個數據的運算
數組和單個數據可直接運算,不需要編寫循環程序處理。

b=np.arange(5)     	# array([0, 1, 2, 3, 4])
b+2 			# array([2, 3, 4, 5, 6])

數組和數組的運算

  1. 數組形狀相同時的運算
    兩個數組形狀(shape)相同時,各位置上的元素對位運算。
a1=np.arange(5)      	# array([0, 1, 2, 3, 4]) 
a2=np.arange(5,10)	# array([5, 6, 7, 8, 9]) 
a1+a2				# array([5, 7, 9, 11, 13])
  1. 數組形狀不同時的廣播運算
    當兩個數組形狀(shape)不同時,如果能按廣播規則擴展爲同形狀的數組,則可以運算,如不符合廣播規則就不能運算。
a1=np.arange(4)    	     # 一維 (4,)  array([0, 1, 2, 3]) 
a2=np.arange(12).reshape(3,4)	# 二維(3,4) 
a1+a2				
array([[ 0,  2,  4,  6],
           [ 4,  6,  8, 10],
           [ 8, 10, 12, 14]])
上例中的a1是一維數組(4,),a2是3x4的二維數組,兩者的維數不同。
a1的維數較小,NumPy在a1的維數前面加1補齊,可近似認爲a1的維數變爲(1,4)。
現在a1的第0維是1,a2的第0維是3,NumPy將把a1的第0維擴充爲3,
相當於將a1的維數變爲(3,4),可認爲a1在內存中被調整爲如下形狀:
array([[0,  1,  2, 3],
           [0,  1,  2, 3],
           [0,  1,  2, 3]]
這樣,a1和a2的形狀一致,就可以完成 a1+a2的運算。

廣播規則

  1. 參加運算的數組都向維數最大的數組看齊,維數較小的數組在前面加1補齊。
  2. 結果數組的形狀(shape)取各運算數組的各個軸上的最大值。
  3. 若運算數組的某個軸的長度爲1,則該軸可擴充爲結果數組的對應軸的長度。若軸的長度不爲1,則不能擴充。
  4. 檢查擴充後所有運算數組對應的軸的長度。若長度都相同則符合規則可以計算,否則違反規則無法計算。
a1=np.array((1,2,3))         a2=np.array((3,4)).reshape(2,1)
形狀爲(3,) 和2x1的兩個數組可運算,結果數組形狀爲2x3。
先是(1,3)(2,1),然後變成(2,3)(2,3)

形狀爲3x1 和1x2的兩個數組可運算,結果數組形狀爲3x2。
形狀爲2x3 和3x2的兩個數組不滿足規則,無法計算。2x3和4x3的數組也無法廣播計算。
結果數組是(3,3),但是(2,3)(3,2)都無法變成(3,3)

數組排序

數組自帶sort()排序方法,按從小到大排列。

np.random.seed(7)
b=np.random.randint(1, 20, size=10)
Out: array([16,  5,  4,  8, 15,  9, 15, 11,  9,  8])

c=b.copy()		# 備份
b.sort()   		# 排序後將改變數組b 
b=c.copy()		# 從備份中恢復b
np.sort(b)  		# np.sort不改變數組本身,返回新的有序數組
x=np.argsort(b)  	# 將返回一個代表原數據順序的有序下標數組
Out: array([2, 1, 3, 9, 5, 8, 7, 4, 6, 0], dtype=int64)
b[x]  			# array([ 4,  5,  8,  8,  9,  9, 11, 15, 15, 16]),花式索引
數組排序不支持列表的reverse=True參數,要從大到小排如下所示:
b[np.argsort(-b)]   	# 注意 -b
Out: array([16, 15, 15, 11,  9,  9,  8,  8,  5,  4])

多維數組排序

多維數組排序時可指定 axis=0() / 1(),排序時默認按最大軸排序。
np.random.seed(7)
b=np.random.randint(1, 50, size=15).reshape(3, 5)
Out:array([[48,  5, 26,  4, 20],
                 [24, 40, 29, 15, 24],
                 [ 9, 26, 47, 43, 27]])

np.sort(b)   		# 默認按axis=1 ,在水平方向上排序
Out:array([[ 4,  5, 20, 26, 48],
           [15, 24, 24, 29, 40],
           [ 9, 26, 27, 43, 47]])

np.sort(b, axis=0)  	# 在豎直方向上排序
Out:array([[ 9,  5, 26,  4, 20],
           [24, 26, 29, 15, 24],
           [48, 40, 47, 43, 27]])

NumPy函數

numpy提供了很多ufunc通用函數,可一次性對整個數組進行計算,無須編寫循環處理。格式:np.函數名(數組)
常用函數
有max()、min()、ptp()、sum()、var()、std()等

np.random.seed(7)
b = np.random.randint(1, 20, size=8) # array([16,  5,  4,  8, 15,  9, 15, 11])
np.max(b), np.min(b) ,np.mean(b)     # 最大值、最小值、平均值
np.ptp(b)			# ptp返回數據極差12,即最大值-最小值
np.quantile(b,[0.25,0.5,0.75])	
# 返回分位點對應的分位數,array([ 7.25, 10.  , 15.  ]),
#這個的意思是佔了這個數組的0.25的前面數字是比7.25小的數字,
#佔了0.5的是數組比10小的數字

一些函數也可寫爲"數組.函數名()"的形式
b.max(),   b.min(),  b.ptp(),  b.sum(),  b.mean()
b.var(),  b.std() , np.median(b)  # 方差、標準差、中位數
b.argmax(),  b.argmin() 	# 最大值、最小值所對應的索引下標

二維數組
對於二維數組,函數計算時還可指定計算的軸axis=0/1。

b = np.arange(10).reshape(2, 5)
Out[7]: 
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
np.sum(b)        		# 未指定軸,計算所有數據的和
Out: 45
np.sum(b, axis=0)        	# 指定軸axis=0,行, 沿豎直方向求和
Out: array([ 5,  7,  9, 11, 13])
np.sum(b, axis=1)        	# 指定軸axis=1,列, 沿水平方向求和
Out: array([10, 35])

缺失值

nan表示缺失值,如數組中含有nan ,則函數運算結果爲nan。
b = np.array([1, 2, np.nan, np.nan, 3]) 	# 構造含有nan值的數組
np.sum(b)    		# 含有nan值的數組,運算後返回nan
np.isnan(b)        	# isnan()測試是否nan值
Out: array([False, False,  True,  True, False])
np.isnan(b).sum()    	 # 計算nan值個數,True被視爲1 ,  結果 2
b[~np.isnan(b)]	# 取出非nan的值
np.nan == np.nan	# nan值很特殊,結果爲False
c = np.arange(1, 6) 	# array([1,2,3,4,5])
np.prod(c)		# 累乘  120
np.cumprod(c)  	# 累乘並給出中間結果  array([1,2,6,24,120])
np.cumsum(c)     	# 累加並給出中間結果
Out: array([1,3,6,10,15], dtype=int32)
b=np.array([1,3,3,5,5,7,8])
np.unique(b)   		# 返回不重複的元素值 array([1, 3, 5, 7, 8])
np.all(b)           		# b所有元素都爲非0值則返回True
np.any(b)         		# b有任意元素爲非0值則返回True
NumPy還提供實現矩陣乘法運算的dot()函數。
a=np.arange(6).reshape(2, 3)
b=np.arange(6, 12).reshape(3, 2)
np.dot(a, b)  #  2x3和3x2數組相乘,結果爲2x2數組。寫爲 a @ b 亦可
Out: 
array([[ 28,  31],
       [100, 112]])

隨機函數

np.random 隨機數模塊
在這裏插入圖片描述

np.random.seed(7)  		# 設置隨機數種子
np.random.rand(2,3)  		# 2x3小數數組
b=np.random.randint(1,100, 20)  # 返回 [1,100)內20個隨機整數
np.random.choice(b, 5)	# 從b中隨機抽5個數據
card=np.arange(1, 55) 		# 一副牌
np.random.shuffle(card)  	# 亂序 (隨機洗牌)
np.argwhere(card==54)	# 查找數據54的位置,array([[2]]

x = ['A',  'B',  'C']
np.random.permutation(x)	# 返回一個排列
Out: array(['C', 'A', 'B'], dtype='<U1')
< : 小端對齊(intelCPU),   U :Unicode編碼          1:1個字符長

# 補充  Python中的排列和組合
import  itertools
list(itertools.permutations(x)) 	     # 返回所有可能的排列
list(itertools.combinations(x, 2)) # x中選2個,返回所有可能組合
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章