比較 布爾邏輯
本節(jié)介紹了使用布爾掩碼來檢查和操作NumPy數(shù)組中的值庐扫。
當您要基于某些條件提取饭望,修改,計數(shù)或以其他方式操縱數(shù)組中的值時形庭,就會出現(xiàn)屏蔽:例如铅辞,您可能希望對大于某個值的所有值進行計數(shù),或者可能刪除高于某個值的所有異常值閾萨醒。在NumPy中斟珊,布爾掩碼通常是完成這些類型任務(wù)的最有效方法。
計算下雨天的例子
在這里富纸,我們將使用Pandas加載2014年西雅圖市的每日降雨量統(tǒng)計信息(每天的降水量)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
# 使用 pandas 提取 下雨的英尺數(shù)作為numpu數(shù)組
rainfall = pd.read_csv('../data/Seattle2014.csv')['PRCP'].values
inches = rainfall / 254.0 # 1/10mm -> inches
inches.shape
## 根據(jù)數(shù)組作圖
import matplotlib.pyplot as plt
#Seaborn其實是在matplotlib的基礎(chǔ)上進行了更高級的API封裝
import seaborn;
seaborn.set(color_codes=True)#設(shè)定顏色
# seaborn.distplot(x, bins=20, kde=False, rug=True);#設(shè)置了20個矩形條
plt.hist(inches, 40);
plt.show();
[圖片上傳失敗...(image-ced9c0-1584522338880)]
該直方圖使我們對數(shù)據(jù)的外觀有了大致的了解:西雅圖的絕大多數(shù)日子在2014年的實測降雨量幾乎為零囤踩。但這并不能很好地傳達我們想要的信息看:例如,一年中有多少雨天晓褪?那些雨天的平均降雨量是多少堵漱?有多少天降雨超過半英寸?
挖掘詳細數(shù)據(jù)
一種解決方法是手動解決這些問題:遍歷數(shù)據(jù)涣仿,每當我們看到某個所需范圍內(nèi)的值時就增加一個計數(shù)器勤庐。出于本章所討論的原因,從時間和計算結(jié)果的角度來看好港,這種方法都效率很低愉镰。我們在NumPy數(shù)組計算中看到:通用函數(shù),可以使用NumPy的ufuncs代替循環(huán)來對數(shù)組進行快速的逐元素算術(shù)運算钧汹。以相同的方式丈探,我們可以使用其他ufunc在數(shù)組上進行逐元素比較,然后我們可以操縱結(jié)果來回答所遇到的問題拔莱。我們現(xiàn)在將數(shù)據(jù)放在一邊类嗤,并討論NumPy中的一些常規(guī)工具,以使用masking快速回答這種類型的問題辨宠。
比較運算符為ufuncs
在numpy數(shù)組通用計算中,我們引入了ufuncs货裹,尤其著重于算術(shù)運算符嗤形。我們看到在數(shù)組上使用+,-弧圆,*赋兵,/和其他會導(dǎo)致按元素進行操作笔咽。 NumPy還實現(xiàn)了比較運算符,例如<(小于)和>(大于)作為元素方式的ufunc霹期。這些比較運算符的結(jié)果始終是具有布爾數(shù)據(jù)類型的數(shù)組叶组。所有六個標準比較操作均可用:
# 與數(shù)組每個比較,也可以使用!= > ==等等
In [5]: 5<np.array([2,6,3])
Out[5]: array([False, True, False])
# 也可以兩個數(shù)組執(zhí)行類似操作
In [7]: b=np.array([1,1,2])
In [8]: a=np.arange(3)
In [9]: a==b
Out[9]: array([False, True, True])
與算術(shù)運算符一樣历造,比較運算符在NumPy中實現(xiàn)為ufunc甩十;當使用x < 3其實調(diào)用內(nèi)部NumPy使用np.less(x,3)吭产。比較運算符及其等效ufunc如下所示:
== np.equal != np.not_equal
< np.less <= np.less_equal
> np.greater >= np.greater_equal
二維數(shù)組
In [27]: rng = np.random.randint(10,size=(3,3))
In [28]: rng
Out[28]:
array([[1, 3, 3],
[8, 7, 2],
[7, 0, 9]])
In [29]: x>6
Out[29]:
array([[False, False, False, False],
[ True, True, False, False],
[False, False, True, False]])
使用布爾數(shù)組
通過數(shù)組布爾運算可以統(tǒng)計很多對我們有用的信息
In [30]: x = np.random.randint(10,size=(3,3))
In [31]: x
Out[31]:
array([[1, 6, 0],
[3, 3, 8],
[0, 9, 7]])
# 計算數(shù)組小于等于3的數(shù)量,也可以使用np.sum(x<=3)
In [33]: np.count_nonzero(x<=3)
Out[33]: 5
用sum匯總的一個好處是可以根據(jù)行或者列來匯總
# 根據(jù)列匯總
In [45]: np.sum(x<=3,axis=0)
Out[45]: array([3, 1, 1])
np.any 和 np.all 方法用來判斷數(shù)組任意一個元素是否符合條件和所有元素是否符合
In [49]: np.any(x<3)
Out[49]: True
In [50]: np.all(x<3)
Out[50]: False
###
In [53]: x
Out[53]:
array([[1, 6, 0],
[3, 3, 8],
[0, 9, 7]])
In [51]: # 判斷每行都是否都大于等于3侣监。可以看到第二行滿足
...: np.all(x >= 3, axis=1)
Out[55]: array([False, True, False])
- 最后 需要注意的是:如聚合:最小臣淤,最大和介于兩者之間的內(nèi)容所述橄霉,Python內(nèi)置了sum(),any()和all()函數(shù)邑蒋。它們的語法與NumPy版本的語法不同姓蜂,特別是在多維數(shù)組上使用時,將失敗或產(chǎn)生意外結(jié)果医吊。對于這些示例钱慢,請確保使用np.sum(),np.any()和np.all()遮咖!
布爾運算符
我們已經(jīng)看到了如何計算滩字,例如,降雨少于四英寸的所有日子御吞,或降雨大于兩英寸的所有日子麦箍。但是,如果我們想知道降雨小于四英寸且大于一英寸的全天陶珠,該怎么辦挟裂?這是通過Python的按位邏輯運算符&,|揍诽,^和?完成的诀蓉。與標準算術(shù)運算符一樣,NumPy將這些重載為ufunc暑脆,它們在(通常為Boolean)數(shù)組中逐個元素地工作渠啤。
In [58]: import numpy as np
...: import pandas as pd
...: # use pandas to extract rainfall inches as a NumPy array
...: rainfall = pd.read_csv('data/Seattle2014.csv')['PRCP'].values
...: inches = rainfall / 254.0 # 1/10mm -> inches
...: inches.shape
Out[58]: (365,)
# 計算降雨量在0.5到1的天數(shù)
In [61]:
...: np.sum((inches > 0.5) & (inches < 1))
Out[61]: 29
運算符等效ufunc運算符等效ufunc
& np.bitwise_and | np.bitwise_or
^ np.bitwise_xor ~ np.bitwise_not
通過這些條件就可以計算我們需要的信息
In [64]: print("Number days without rain: ", np.sum(inches == 0))
...: print("Number days with rain: ", np.sum(inches != 0))
...: print("Days with more than 0.5 inches:", np.sum(inches > 0.5))
...: print("Rainy days with < 0.2 inches :", np.sum((inches > 0) &
...: (inches < 0.2)))
Number days without rain: 215
Number days with rain: 150
Days with more than 0.5 inches: 37
Rainy days with < 0.2 inches : 75
布爾數(shù)組作為掩碼參與數(shù)組運算
在上面,我們研究了直接在布爾數(shù)組上計算的聚合添吗。一種更強大的模式是使用布爾數(shù)組作為掩碼沥曹,以選擇數(shù)據(jù)本身的特定子集。從前面返回x數(shù)組,假設(shè)我們想要一個數(shù)組妓美,該數(shù)組的所有值都小于5僵腺,例如:
In [65]: x
Out[65]:
array([[1, 6, 0],
[3, 3, 8],
[0, 9, 7]])
#可以很容易地為此條件獲得一個布爾數(shù)組:
In [69]: test=x<3
In [70]: test
Out[70]:
array([[ True, False, True],
[False, False, False],
[ True, False, False]])
現(xiàn)在要從數(shù)組中選擇這些值,我們只需在此布爾數(shù)組上建立索引即可壶栋;這稱為屏蔽操作:
#根據(jù)test的索引對應(yīng)x數(shù)組選擇True的值
In [71]: x[test]
Out[71]: array([1, 0, 0])
應(yīng)用到上面統(tǒng)計下雨天的例子中
# construct a mask of all rainy days
rainy = (inches > 0)
# construct a mask of all summer days (June 21st is the 172nd day)
days = np.arange(365)
summer = (days > 172) & (days < 262)
print("雨天的中位數(shù): ",
np.median(inches[rainy]))
print("夏天雨天的中位數(shù): ",
np.median(inches[summer]))
print("夏季雨天最大降水量: ",
np.max(inches[summer]))
print("非夏天雨天的中位數(shù):",
np.median(inches[rainy & ~summer]))
通過組合布爾運算辰如,屏蔽運算和聚合,我們可以非彻笫裕快速地為我們的數(shù)據(jù)集回答這類問題琉兜。
易混淆
當使用&和|在整數(shù)上,表達式對元素的位進行運算锡移。當使用and或or時呕童,等效于要求Python將對象視為單個布爾實體。在Python中淆珊,所有非零整數(shù)都將評估為True夺饲。
In [75]:
...: bool(42), bool(0)
Out[75]: (True, False)
In [76]: bool(42 or 0)
Out[76]: True
# 位運算
In [77]: bin(42 & 59)
Out[77]: '0b101010'