NumPy的各種用法 - 讀書筆記 - Python Data Science Handbook - Python數據科學 - NumPy聚合操作 Aggregation - NumPy 廣播運算 Broadcasting - 如何操作布林數組,快速找到我們要的元素值Comparisons、Masks、Boolean Logic -筆記#8

為自己Coding
·
·
IPFS
·


Github連結


這篇是延續上一篇2.5章後面的內容喔,因為太'長了,所以我把它切成兩部分來說明喔


攝影師:Michael Block,連結:Pexels


2.5章 廣播 Broadcasting - 數組上的運算


4. 廣播 實作 - 中心化方法

  • 我們已經知道ufuncs提供了可以避免使用Python循環低效的方式,然而廣播大大地擴展了這個能力
  • 舉例: 數據中心化(Centering an array)
  • 例子: 假設我們進行10次採樣,每次都會得到3個數據值
import numpy as np
​
X = np.random.random((10,3))
X

執行結果

array([[0.61395157, 0.63672235, 0.2819929 ],
   [0.01319829, 0.76408163, 0.3923268 ],
   [0.49654391, 0.48526054, 0.80337583],
   [0.52355967, 0.65514011, 0.77710867],
   [0.38722043, 0.45083486, 0.33298208],
   [0.31160497, 0.17435645, 0.32452177],
   [0.58727465, 0.97500597, 0.42886587],
   [0.99165537, 0.43683679, 0.51030536],
   [0.80680708, 0.52657516, 0.38738793],
   [0.81282071, 0.7912729 , 0.127596 ]])
  • mean: 使用mean函數來沿著第一個維度求出美個特徵的平均值
## 根據列來取平均值,也就是每個特徵的平均值
Xmean = X.mean(axis = 0)
Xmean

執行結果

array([0.55446366, 0.58960868, 0.43664632])
  • 中心化: 將原本數據的個元素減掉平均值,就可以將數據集中心化(這邊就是一個廣播操作的例子)
## 中心化
X_centered = X - Xmean
X_centered

執行結果

array([[ 0.05948791, 0.04711367, -0.15465342],
   [-0.54126537, 0.17447295, -0.04431952],
   [-0.05791976, -0.10434814, 0.36672951],
   [-0.030904 , 0.06553143, 0.34046235],
   [-0.16724324, -0.13877381, -0.10366424],
   [-0.24285869, -0.41525222, -0.11212455],
   [ 0.03281098, 0.3853973 , -0.00778045],
   [ 0.4371917 , -0.15277188, 0.07365904],
   [ 0.25234341, -0.06303352, -0.04925839],
   [ 0.25835705, 0.20166423, -0.30905032]])
  • 檢查結果的正確性: 透過查看進行中心化後的數組在各特徵上的平均值是否夠接近於0
## 根據列來取平均值
X_centered.mean(0)

執行結果

array([ 4.44089210e-17, 5.55111512e-17, -8.88178420e-17])
  • 結果: 根據機器準確度(machine precision)的情況,平均值已經是等於0了



5. 視覺化 - 廣播應用於二維函數來顯示圖像

  • 廣播有一個非常有用的地方,就是根據二維函數來顯示圖像
  • 舉例: 如果我們要定義一個函數z = f(x, y) ,就可以使用廣播(Broadcasting)來計算整個網路中的函數
## 創建x和y數據資料 從0到5,總共有50步
x = np.linspace(0, 5, 50)
## [:, np.newaxis]改變形狀: 垂直
y = np.linspace(0, 5, 50)[:, np.newaxis]
​
## z 值公式
z = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)


視覺化

## 視覺化
## 導入視覺化套件
%matplotlib inline
import matplotlib.pyplot as plt
​
## 顯示圖像
plt.imshow(z, origin = 'lower',
     extent = [0, 5, 0, 5],
     cmap = 'viridis_r')
​
## 顯示顏色對應數值條
plt.colorbar()


執行結果




2.6章 比較、遮蓋和布林邏輯 Comparison, Masks, and Boolean Logic


1. 布林遮蓋(掩碼) Boolean Masks 是什麼?

  • 當想透過一些表準條件來對數組中的元素值進行提取、修改、技術或著其他操作時,我們就需要用到遮蓋(Masks)
  • 舉例: 當我們希望計算大於某個特定值的元素個數,或著刪除高於某個閾值的異常值(離群值),在NumPy當中,就會使用布林遮蓋Boolean Masks來達成


2. 實作 - 計算下雨的天數 - 上半部

這邊使用的是書本中,作者所提供的2014西雅圖的每天將與統計數據

  • 載入數據集
## 導入所需套件
import numpy as np
import pandas as pd
​
## 載入數據集
dataset = pd.read_csv('dataset/Seattle2014.csv')
​
## 顯示數據集
dataset
​




  • 取出降雨量欄位的所有元素值,並准換單位為英寸
## 取出降雨量的元素值,並組成NumPy Array
rainfall = dataset['PRCP'].values
# print(rainfall)
​
## 將單位轉換成英寸 inches: 1/10mm -> inches
inches = rainfall / 254.0
# print(inches)
​
## 查看大小
print(inches.shape)

執行結果

(365,)

這個數組共有365個值,代表西雅圖一年365天的降雨(單位為英寸: inches)



視覺化: 使用直方圖來視覺化出降玉天數的分布情況

## 導入視覺化套件
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn; seaborn.set()
​
​
## 畫出直方圖 後面的60是bins參數:表示總共有幾條直方 
plt.hist(inches, 60)

執行結果




  • 上面的視覺化幫助我們概略的了解了這個數據集,但是這張圖並沒有幫助我們得到更多的資訊,像是一年中有多少天在下雨?下雨的日子中降水量的平均值是多少?一年中有多少降雨量超過半英寸?



3. UFuncs 比較運算符 - NumPy中用來遮蓋(Masks)的通用工具

  • 之前介紹UFuncs的章節,只介紹了算數運算符(+、-、*、/等等),來對數組進行逐個元素的計算操作
  • NumPy也可以實現比較運算符(>大於、<小於)的ufuncs,這些比較運算符的結果一定是布林值(True or False)數組
a = np.array([1,2,3,4,5,6])
a < 3.5
## array([ True, True, True, False, False, False])
a > 3.5
## array([False, False, False, True, True, True])
a >= 3.5
## array([False, False, False, True, True, True])
a <= 3.5
## array([ True, True, True, False, False, False])
a != 3
## array([ True, True, False, True, True, True])
a == 3
## array([False, False, True, False, False, False])
  • 更多應用: 也可以將兩個數組的元素逐個進行比較,支援運算的組合操作比較
4 * a == a ** 2
## array([False, False, False, True, False, False])
  • 圖表為比較運算符的簡潔寫法和其對應的ufuncs寫法



  • 比較運算符也可以應用在任何形狀(shape)的數組上喔
## RandomState: 控制隨機的方式
## 如果跟我一樣設2 就會生成一樣的二為數組喔
rng = np.random.RandomState(2)
x = rng.randint(10, size = (3, 5))
x
## 執行結果
array([[8, 8, 6, 2, 8],
   [7, 2, 1, 5, 4],
   [4, 5, 7, 3, 6]])
x >= 5
## 執行結果
array([[ True, True, True, False, True],
   [ True, False, False, True, False],
   [False, True, True, False, True]])


重要觀念: 比較運算符的結果都為布林型的數組,而NumPy提供了眾多可以操作這類型數組的函數


4. 操作布林數組 Working with Boolean Arrays - <、>、==、<=、>=、!=

當我們透過UFuncs比較符號計算出一個布林數組時,接下來我們需要對這個布林數組進行一些運算操作,來得到更多數據的資訊

  • 創建一個二維數組
## RandomState: 控制隨機的方式
## 如果跟我一樣設2 就會生成一樣的二為數組喔
rng = np.random.RandomState(2)
a = rng.randint(10, size = (3, 5))
a

執行結果

array([[8, 8, 6, 2, 8],
   [7, 2, 1, 5, 4],
   [4, 5, 7, 3, 6]])


np.count_nonzero - 計算為數組中True的數量

## 計算多少值低於7
np.count_nonzero(a < 7) # 10

結果: 從結果可以看出小於7的元素共有十個,另一種用來獲取這種資訊的方式是np.sum


np.sum - 計算為數組中指定條件的元素數量

  • 操作原理: 把符合與不符合條件的元素標記為True或False,False會被當成是0,而True會被當成是1,然後相加就會得到True的數量
## 計算多少值低於7
np.sum(a < 7) # 10
  • 優點: 使用np.sum的好處在也可以根據行或列來進行計算
  • 根據行來找尋小於7的元素數量
## 每一行中小於7的元素數量
np.sum(a < 7, axis = 1)

執行結果

array([2, 4, 4])


np.any & np.all - 用來檢查當我們有任何一個或全部都為True(符合條件)的值

## RandomState: 控制隨機的方式
## 如果跟我一樣設2 就會生成一樣的二為數組喔
rng = np.random.RandomState(2)
a = rng.randint(10, size = (3, 5))
a

執行結果

array([[8, 8, 6, 2, 8],
   [7, 2, 1, 5, 4],
   [4, 5, 7, 3, 6]])
  • np.any & np.all用法
## 有模有任何一個值大於9
np.any(a > 9) # False
## 有沒有任何一個值小於2
np.any(a < 2) # True
## 是不是所有的元素都小於9
np.all(a < 10) # True
## 是不是所有值都不等於7
np.all(a != 7) # False
  • np.any 和 np.all 也可以根據特定的軸進行運算喔
## 是不是每一行都所有元素值都大於6
np.all(x > 2, axis = 1)

執行結果

array([False, False, True])

前兩行都不是全部元素都大於2,只有第三行的元素都大於2


重點提醒

Python也有內建的sum()、any()、all()函數,但他們與NumPy相對應的函數有著不同的語法,尤其是計算多維數組的時候,可能報錯或無法預料的結果



實作 - 計算下雨的天數 - 下半部

接下來的實作都會使用這個數據集當例子喔



5. 布林操作符 - Boolean Operators - 按位邏輯運算符 Bitwise Logic Operators、& 、|、^、~

我們能夠透過前面教的計算操作知道,有多少天雨量少於4 inches,或是多少天雨量大於2inches,但是我們接下來想知道的是多少天雨量少於6 inches且大於2inches?

  • Python的方法: 這時候就需要透過Python的按位邏輯運算符(bitwise logic operators)、&、|、^和~來達成
  • NumPy的方法: NumPy將上面的Python方法重載到UFuncs裡面,來對數組(通常是布林數組)中每個元素進行操作
  • 前面轉換成英寸的降雨量數據
## 每天的降雨量數據
inches

執行結果

array([0.   , 0.16141732, 0.05905512, 0.   , 0.   ,
   0.01181102, 0.48031496, 0.38188976, 0.22834646, 0.16929134,
   0.83858268, 0.05905512, 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.01968504, 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.3503937 , 0.8503937 , 0.   ,
   0.09055118, 0.07874016, 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.2007874 , 0.01968504,
   0.72047244, 0.66929134, 0.18110236, 0.07086614, 0.37007874,
   0.46062992, 1.03937008, 0.57086614, 0.5984252 , 0.03937008,
   0.11811024, 0.11023622, 0.0984252 , 0.24015748, 0.51181102,
   0.01181102, 0.   , 0.   , 0.   , 0.01968504,
   0.7519685 , 0.42125984, 0.6496063 , 1.83858268, 0.11811024,
   0.   , 1.27165354, 0.16929134, 0.74015748, 0.   ,
   0.   , 0.01968504, 0.27165354, 0.31889764, 1.09055118,
   0.01181102, 0.   , 0.01968504, 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.16141732, 0.14173228,
   0.01181102, 0.87007874, 0.5511811 , 0.   , 0.   ,
   0.   , 0.   , 0.0984252 , 0.   , 0.18110236,
   0.   , 0.   , 0.18110236, 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.01968504,
   0.42913386, 0.72834646, 0.   , 0.53937008, 0.   ,
   0.2007874 , 0.55905512, 0.3503937 , 0.48818898, 0.   ,
   0.12992126, 0.27165354, 0.   , 0.   , 0.   ,
   0.   , 0.   , 1.31102362, 0.62992126, 0.2007874 ,
   0.   , 0.   , 0.53937008, 0.07874016, 0.01968504,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.1496063 , 0.   , 0.22047244,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.07086614, 0.2519685 , 0.   ,
   0.01968504, 0.14173228, 0.0511811 , 0.   , 0.03149606,
   0.01181102, 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.07086614, 0.09055118, 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.01181102, 0.75984252, 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.01968504, 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.01968504, 0.5   , 0.8503937 ,
   0.   , 0.03937008, 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.33070866, 0.0511811 , 0.   , 0.11811024,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.01968504,
   0.01181102, 0.   , 0.   , 0.   , 0.01181102,
   0.72047244, 0.7992126 , 0.16929134, 0.3503937 , 0.   ,
   0.   , 0.03149606, 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.01181102, 0.29133858, 0.   ,
   0.2992126 , 0.27952756, 0.33858268, 0.   , 0.12992126,
   0.59055118, 0.   , 0.46062992, 0.03937008, 1.25984252,
   0.37007874, 0.16141732, 0.24015748, 0.05905512, 0.03149606,
   0.5   , 0.01968504, 1.   , 0.66929134, 0.   ,
   0.07086614, 0.42913386, 0.16141732, 0.18897638, 0.16141732,
   0.   , 0.   , 0.2007874 , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.   , 0.   , 0.   , 0.14173228, 0.5984252 ,
   0.01968504, 0.46850394, 0.0511811 , 0.72047244, 0.01181102,
   0.12992126, 1.3503937 , 0.14173228, 0.   , 0.   ,
   0.   , 0.   , 0.03149606, 0.11811024, 0.29133858,
   0.   , 0.35826772, 0.38976378, 0.51181102, 0.27165354,
   0.   , 0.   , 0.   , 0.   , 0.   ,
   0.11023622, 0.51181102, 0.11811024, 0.77165354, 0.   ,
   0.   , 0.81102362, 0.20866142, 0.   , 0.   ,
   0.12992126, 0.16141732, 0.   , 0.   , 0.   ])
  • 有多少天降雨量介於0.5 inches到1 inches之間
## 找出大於0.5且小於1的元素值
##print((inches > 0.5) & (inches < 1))
​
## 統計True的個數,統計符合大於0.5且小於1的元素值
np.sum((inches > 0.5) & (inches < 1)) # 29
  • 統計不符合大於1或是小於等於0.5的元素值的數量
## 找出大於1或是小於等於0.5的元素值
##print((inches > 1) | (inches <= 0.5))
​
## 將上面的條件相反過來 - 取not,也就是不符合大於1或是小於等於0.5的元素值
##print(~((inches > 1) | (inches <= 0.5)))
​
## 計算True的數量,統計不符合大於1或是小於等於0.5的元素值的數量
np.sum(~((inches > 1) | (inches <= 0.5))) # 30
  • 圖表: 符號對應UFuncs表



  • 統計各種條件
print('沒有降雨的天數: ', np.sum(inches == 0))
print('有降雨的天數: ', np.sum(inches != 0))
print('降雨量大於0.6 inches的天數: ', np.sum(inches > 0.6))
print('降雨量介於0.2到0.6之間的天數: ', np.sum((inches > 0.2) & (inches < 0.6)))

執行結果

沒有降雨的天數: 215
有降雨的天數: 150
降雨量大於0.6 inches的天數: 26
降雨量介於0.2到0.6之間的天數: 49



6. 遮蓋 - 布林數組 Boolean Arrays as Masks - 直接返回符合條件的元素值,而不是返回True或False


舉例 : 我們想知道數組中所有大於5的元素值有哪些?

  • 創建一個二維數組
## RandomState: 控制隨機的方式
## 如果跟我一樣設2 就會生成一樣的二為數組喔
rng = np.random.RandomState(2)
a = rng.randint(10, size = (3, 5))
a

執行結果

array([[8, 8, 6, 2, 8],
   [7, 2, 1, 5, 4],
   [4, 5, 7, 3, 6]])
  • 找出符合條件的有幾個元素
## 大於5的元素值,返回布林數組
a > 5

執行結果

array([[ True, True, True, False, True],
   [ True, False, False, False, False],
   [False, False, True, False, True]])
  • 找出符合條件的元素值
## 大於5的元素值,返回一維數組裝載符合條的的元素值
a[a > 5]

執行結果

array([8, 8, 6, 8, 7, 7, 6])


利用剛剛建立好的布林數組當作索引,來對原數組進行搜尋,找到所有對應True的元數值

結果: 傳回一個一維數組,裡面裝載著滿足設定條件的元素值; 也就是說,掩碼數組(Mask Array)為True的位置中的所有值喔

  • 利用這個遮蓋(Masks)方法,來對我們的降雨數據進行各種統計操作
## 建構一個下雨天的遮蓋(Mask)
rainy = (inches > 0)
​
## 建構一個晴天的遮蓋(Mask) - 6/21號是第172天
days = np.arange(365)
summer = (days > 172) & (days < 262)
​
​
print("2014年下雨天的中位(Median Precip)降雨量: ", np.median(inches[rainy]))
print("2014年晴天的中位(Median Precip)降雨量: ", np.median(inches[summer]))
print("2014年晴天的最大(Max Precip)降雨量: ", np.max(inches[summer]))
print('2014年不為晴天的中位(Median Precip)降雨量: ', np.median(inches[rainy & ~summer]))

執行結果

2014年下雨天的中位(Median Precip)降雨量: 0.19488188976377951
2014年晴天的中位(Median Precip)降雨量: 0.0
2014年晴天的最大(Max Precip)降雨量: 0.8503937007874016
2014年不為晴天的中位(Median Precip)降雨量: 0.20078740157480315


結合了布林操作、遮蓋操作和聚合,我們可以從數據集中得到更多的統計資訊



7. 關鍵字 and/or vs &/|


疑問: 使用and/or,和使用&/|的差別?

  • and/or: 測量整個對象(object)的真假
  • &/|: 引用對象中的每個位(bits)
  • 每當使用and或or時,等同於要求Python將物件(object)視為單個布林實體
bool(66), bool(0) # (True, False)
bool(66 and 0) # False
bool(66 or 0) # True
  • 在Python中,所有非零整數都將估計為True
  • 當使用&和|在整數上時,表達式會對元素的位(bit)進行運算,簡單來說會對每個位(bits)進行and或or計算 - ex.1and0 會等於0(False),而1or0會等於1(True)
bin(68) # '0b1000100'
bin(58) # '0b111010'
bin(55 & 66) # '0b1110111'


重要提醒: 比較了二進制表示刑事的相應位,來得出結果

  • 當我們在NumPy中有布林數組,我們可以將它視為一個0和1組成的字符串,1代表True,而0代表False,然後使用&和|來得到結果
a = np.array([1,0,0,1,1,1,0,0,0,1], dtype = bool)
b = np.array([0,1,0,1,0,0,1,1,1,0], dtype = bool)
​
a | b

執行結果

array([ True, True, False, True, True, True, True, True, True,
   True])
  • 如果使用or來評估整個物件(object)的真假,但這不是一個明確定義的值
a or b

執行結果

---------------------------------------------------------------------------
ValueError               Traceback (most recent call last)
<ipython-input-98-51429399a6cf> in <module>
----> 1 a or b
​
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
  • 結果: 在給定數組上執行布林表達式時,應該要使用|或是&,而不是使用and和or
x = np.arange(10)
(x > 3) & (x < 9)

執行結果

array([False, False, False, False, True, True, True, True, True,
   False])
  • 使用and來評估整個數組的真實性或是虛假性會給我們帶來與之間結果相同的錯誤- ValueError
(x > 3) and (x <9)

執行結果

---------------------------------------------------------------------------
ValueError               Traceback (most recent call last)
<ipython-input-104-0b2c6dfa091b> in <module>
----> 1 (x > 3) and (x <9)
​
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()



結論

  • and/or: 測量整個對象(object)的真假
  • &/|: 引用對象中的每個位(bits)

對於NumPy中的布林數組,通常都會使用&和|來進行操作

CC BY-NC-ND 2.0 授权

喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!

為自己CodingYO~~ 剛跨入AI人工智慧領域的小小工程師, 熱愛自學, 熱愛分享, 下班後的我想為自己Coding, 積極撰寫教學文, 想將自學的程式知識分享給大家, 不斷追求進步的自己, 希望有一天能回饋社會,幫助需要幫助的人, 如果您有什麼很酷的想法,也覺得我還行,歡迎您找我合作~~ IG: https://www.instagram.com/coding_4_me/
  • 来自作者
  • 相关推荐

[Takeaways]原力效應 — Part1

[行銷5.0] 人工智慧的緣起

[Aptos學習筆記#8]Move進階使用 - Resource介紹一