L:python的Numpy模塊:集合函數,多項式,數組組合和文件存取

集合函數

研究兩個數組中的數據是否存在某種集合關係時,可使用集合函數。

x=np.arange(5)  	# array([0,1,2,3,4]) 
y=np.arange(3, 8)  	# array([3,4,5,6])

np.intersect1d(x, y) 	# 交集 , 注:不能使用集合的運算符號& | -
Out:array([3, 4])	# 1d 表示返回結果總是一維數組
np.union1d(x, y)	# 並集
Out:array([0, 1, 2, 3, 4, 5, 6, 7])

np.setdiff1d(x, y)	# 差集 x - y
Out: array([0, 1, 2])
np.setxor1d(x, y)	# 對稱差集, 不同時存在於x/y集合中
Out: array([0, 1, 2, 5, 6, 7])

多項式

np可構造多項式,可代入數值進行計算,還可求微分、積分、解方程。

y = np.poly1d([1, -3, -4])  # 以列表形式給出多項式係數,y是構造的多項式
Out: poly1d([ 1, -3, -4])    	#  y = x2 - 3x - 4

y([0.5, 1, 1.5])         		# 分別計算x取0.5, 1, 1.5時多項式的值
Out: array([-5.25, -6.  , -6.25])

np.roots(y)  		         	# 計算方程 的根
Out: array([ 4., -1.])   		# 根爲4和-1

p = np.poly1d([2, 4, 0, 3]) 	# 構造多項式p=2x3 + 4x2 + 3 
z = p+y                  		# p, y 兩個多項式相加
Out: poly1d([ 2,  5, -3, -1])	# z = 2x3 + 5x2 - 3x - 1

z.deriv()       			# 微分
Out:poly1d([6, 10, -3])		# z' = 6x2 + 10x - 3
z.integ()  	     		# 積分
poly1d([ 0.5    ,  1.66666667, -1.5     , -1.    ,  0.   ])

多項式擬合:利用給定的自變量和因變量,按指定的最高次方擬合多項式。
x=[1, 2, 3] ; y=[ 2, 4.2, 5.8] 按一次式擬合 y = 1.9 x + 0.2

x = np.arange(1, 21)			# 自變量
y1 = 3 * x + 2 + np.random.rand(20) 	# 構造測試數據y1並加入隨機干擾值
coef = np.polyfit(x, y1, 1)         		# 按一次多項式擬合,擬合係數如下
Out: array([2.99028312, 2.5900484 ])   #  y = 2.99x + 2.59
yn = np.poly1d(coef)  			# 擬合的多項式
yn(x)	# 計算擬合值, 和  y1 對比一下,比較接近

y2 = x**2 + 3 * x + 1 + np.random.rand(20)	# 構造測試數據y2
np.polyfit(x, y2, 2)              		# 按二次多項式擬合,擬合係數如下
Out: array([1.00000149, 3.01755285, 1.32390592]) # y = x2 + 3.02x +1.32

以貓圖爲例的數組應用

import numpy as np
from PIL import Image
a = np.array(Image.open('cat.jpg'))
# 高x寬x顏色,數據類型,某個點的顏色值
print(a.shape, a.dtype, a[0,0,:])

b = 255 - a  # 互補色  RGB(255,0,0)
im = Image.fromarray(b.astype('uint8'))
im.save('cat2.jpg')

在這裏插入圖片描述

c = a.copy()
c[::2] = 0         #黑色橫條
Image.fromarray(c).save('cat3.jpg')

c = a.copy()
c[:, ::2] = 255 #白色豎條
Image.fromarray(c).save('cat4.jpg')

在這裏插入圖片描述

#上下顛倒
Image.fromarray(a[::-1]).save('cat5.jpg')
#左右交換
Image.fromarray(a[:, ::-1]).save('cat6.jpg')

在這裏插入圖片描述

#水平組合
Image.fromarray(np.hstack((a,a))).save('cat7.jpg')
#垂直組合
Image.fromarray(np.vstack((a,a))).save('cat8.jpg')

在這裏插入圖片描述

#用tile平鋪:縱/橫軸都爲2倍,顏色軸爲1倍不變
Image.fromarray(np.tile(a, (2, 2, 1))).save('cat9.jpg')
#用repeat重複1軸 2次
Image.fromarray(np.repeat(a, 2, axis=1)).save('cat10.jpg')

在這裏插入圖片描述

數組組合和文件存取

改變數組維度:np提供瞭如下方法可改變數組的維度

1. reshape()方法
b=np.arange(12)
c=b.reshape(3, 4)    # b不變,得到新的c,reshape()得到的是視圖
d=c.reshape(-1, 6)   # -1表示此軸的值由np自動計算得到
e=c.reshape(2, -1)   # -1表示此軸的值由np自動計算得到
b.shape, c.shape, d.shape, e.shape
Out: ((12,), (3, 4), (2, 6), (2, 6))

2.設置shape屬性或使用 resize() 方法
b.shape=(3, 4) 	# 直接改變b的形狀
b.resize((3, 4)) 	# 直接改變b

3. 轉置矩陣: 將行/列交換
d=c.transpose()   #  或  c.T
4. 增加一個維度
ar = np.array([3,4,5]) # 原本是一維    ar.shape  (3,)
ar2 = ar[:, np.newaxis]  # 增加一個維度,變爲二維。很多機器學習程序中處理數據集需要增加數據的維度。 ar2.shape  (3, 1)
ar3 = ar2[:, :, np.newaxis]  # ar3 三維
5. 將多維數組展平爲一維數組
d1=b.ravel() 	# 將多維的b轉爲一維的d1, 視圖
d2=b.flatten() 	#將多維的b轉爲一維的d2, 是複製,不是視圖

數組元素的插入、刪除

b=np.array([1, 3, 5, 7])
c=np.append(b, [9, 10])   # 插入, b不變,返回新數組c
Out:array([1,  3,  5,  7,  9, 10])

np.insert(b, 2, 20)   # 在第2個位置插入20, b不變,返回新數組
Out:array([1,  3, 20,  5,  7])
np.delete(b, [0,1])  # 刪除第[0,1]處數據,b不變,返回刪除後的新數組
Out:array([5, 7])

數組組合

a = np.arange(6).reshape(2, 3)
b = np.arange(10, 16).reshape(2, 3)

1.水平組合 (複製)

np.hstack((a,b))  		# 水平組合。行數不變,列數增加

np.concatenate((a,b),  axis=1)  # 效果同上
np.column_stack((a,b)) 	# 效果同上

2.垂直組合

np.vstack((a,b))  		# 垂直組合。行數增加,列數不變

np.concatenate((a,b),  axis=0)  # 效果同上
np.row_stack((a,b)) 		# 效果同上

3.深度組合

c=np.dstack((a,b)) # 深度組合。a,b本是二維,c是三維

在這裏插入圖片描述

數組分割

1.水平分割 (視圖)

b = np.arange(24).reshape(4, 6)	# 生成4x6數組

x1, x2 = np.hsplit(b, 2) 	 	# 沿水平方向分爲2個相同大小的4x3數組

x1, x2, x3 = np.hsplit(b, 3)  	# 沿水平方向分爲3個相同大小的4x2數組

# x4含原數組第0列,x5含第1、2、3列,x6含的第4、5列
x4, x5, x6 = np.hsplit(b, [1, 4]) 	# 在第1, 4列分隔 

在這裏插入圖片描述
2.垂直分割

b = np.arange(24).reshape(4, 6)	# 4x6數組
y1, y2 = np.vsplit(b, 2) 	 	# 沿垂直方向分爲2個相同大小的2x6數組

np.vsplit(b, 4)  	# 沿垂直方向分爲4個相同大小的1x6數組

在這裏插入圖片描述
3.深度分割

b = np.arange(24).reshape(2, 3, 4)	# 2x3x4數組
v1, v2 = np.dsplit(b, 2) 	 	# 沿深度分爲2個相同大小的2x3x2數組
v1.shape, v2.shape
Out: ((2, 3, 2), (2, 3, 2)) 
注:dsplit()只能用於維度>=3的數組,不能用於一、二維數組	

讀寫文件

NumPy可以讀寫文本和二進制數據文件。
1.讀寫文本文件

b=np.arange(95, 101).reshape(2,3)
np.savetxt('data.txt', b)  # 將數組b保存到data.txt 文件中,保存時默認按科學計數法格式

# 指定以逗號','分割, %i整數格式保存
np.savetxt('data2.txt', b, delimiter=',', fmt='%i')  
!type  data2.txt      # 顯示data2.txt文件內容
95,96,97
98,99,100
c=np.loadtxt('data2.txt',  delimiter=',')   # 讀文本數據文件

2.讀寫.npy二進制格式文件

np.save('data', b)  # 將數組b保存爲data.npy文件,自動加擴展名.npy
d=np.load('data.npy')  	# 讀取npy格式的二進制文件
b==d   			# 驗證 b和d 是相等的
注:data.npy不能被pickle讀取,因爲二進制文件格式不同。

應用例子

節用NumPy給出一個骰子研究實例。有三顆骰子,每次一起拋出,現在用隨機函數模擬拋擲1000(1000x3)。
這1000次中有多少次投出“666”?有多少次出現三個骰子點數一樣的情況?
如果假定最初有500個籌碼,三個骰子的點數之和大於10算贏,小於等於10算輸,
每次輸贏一個籌碼,那麼最後是贏還是輸?曾經達到的最大輸贏數是多少?
import numpy as np
np.random.seed(7) 				# 註釋該行則每次測試有變化
num = 1000				# 拋擲總次數
# 產生1000x3數組dice,隨機整數範圍[1,6],注意函數中要寫爲7
dice = np.random.randint(1, 7, size=(num, 3))
# 爲編程方便,計算三個骰子的點數之和,添加到dice末尾列,現在是1000x4數組
dice = np.column_stack((dice, dice.sum(axis=1)))
point = dice[:, 3]                 			# 取點數之和列(第3列)
print('投擲出666的次數:', (point == 18).sum())  	# 出現666的次數
print('666出現在第x次', np.where(point == 18)) 	# 出現在第x次

# 找出三次投擲點數一樣的行,得到一個布爾數組,注意 np.logical_and 函數
condition = np.logical_and(dice[:, 0] == dice[:, 1], dice[:, 1] == dice[:, 2])
print('\n三次投擲點數均相同的次數:', condition.sum())  	# 計算True的次數
print('投擲情況爲:', dice[condition])  		# 顯示True對應的行
money = 500	# 初始籌碼數
bep = 10		# >10贏,<=10輸

print('\n初始籌碼:', money, ', 盈虧點:', bep, ', 每次輸贏1')
# 只需簡單統計> bep和<= bep的次數之和,即可計算最後的籌碼數
total = money + (point > bep).sum() - (point <= bep).sum()
print('最後籌碼:', total)
# 計算投擲過程中曾經達到的最高籌碼數、最低籌碼數
# np.where判斷每次輸贏,返回1,-1構成的每次盈虧列,添加到末尾列,變爲1000x5
dice = np.column_stack((dice, np.where(dice[:, 3] > bep, 1, -1)))
# np.cumsum累加每次盈虧列,得到累積盈虧列,添加到末尾列,變爲1000x6
dice = np.column_stack((dice, np.cumsum(dice[:, 4])))

# 累積盈虧列加初始籌碼數,得到當前籌碼列,添加到末尾列,變爲1000x7
dice = np.column_stack((dice, dice[:, 5] + money))
s = '曾經的最高籌碼數{}, 出現在第{}次'
print(s.format(np.max(dice[:, 6]), np.argmax(dice[:, 6])))
s = '曾經的最低籌碼數{}, 出現在第{}次'
print(s.format(np.min(dice[:, 6]), np.argmin(dice[:, 6])))

np.set_printoptions(threshold=10000)  # 輸出數據個數的門檻
#籌碼變化圖
import matplotlib.pyplot as plt		# 引入繪圖庫
plt.rcParams['font.sans-serif'] = ['SimHei']	# 指定中文黑體字體
plt.xticks(fontsize=14)		# 設x軸文字大小
plt.yticks(fontsize=14)		# 設y軸文字大小
plt.title('籌碼變化', fontsize=16) 		# 設標題文字
plt.plot(dice[:, -1]) 			# 畫籌碼變化折線圖

投擲出666的次數: 2
666出現在第x次 (array([ 99, 865], dtype=int64),)
三次投擲點數均相同的次數: 22
投擲情況爲: [[ 5 5 5 15] … …
初始籌碼: 500 , 盈虧點: 10 , 每次輸贏1
最後籌碼: 442
曾經的最高籌碼數504,出現在第57次
曾經的最低籌碼數431, 出現在第810次
在這裏插入圖片描述

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