numpy中的布尔索引(实例讲解)
import numpy as np
import pandas as pd
从github中获取西雅图2014年的降水量数据,将0.1mm的单位转成英寸单位。
file = 'https://raw.githubusercontent.com/codebysandwich/PythonDataScienceHandbook/master/notebooks/data/Seattle2014.csv'
rainfall = pd.read_csv(file)['PRCP'].values
inches = rainfall / 254 # 1/10 mm -> inches 转化为英寸单位
inches.shape
(365,)
这个数组包含365个数据,先可视化一下数据, 看下下雨数据的直方图:
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn; seaborn.set() # 设置绘图风格
plt.hist(inches, 40)
plt.show()
大多数数据都是近于0的,可以看到有多少是小于0.5英寸的?
举几个和通用函数类似的布尔逻辑操作的例子
x = np.array([1, 2, 3, 4, 5])
x < 3
array([ True, True, False, False, False])
x > 3
array([False, False, False, True, True])
np.less(x, 3) # 通用函数 等价于 < 操作符
array([ True, True, False, False, False])
逻辑比较得到布尔数组,那么这些布尔数组对我们来说有什么用呢?
操作布尔数组
rng = np.random.RandomState(0)
x = rng.randint(10, size=(3, 4))
x
array([[5, 0, 3, 3],
[7, 9, 3, 5],
[2, 4, 7, 6]])
x < 6 # 获取布尔数组
array([[ True, True, True, True],
[False, False, True, True],
[ True, True, False, False]])
np.count_nonzero(x < 6) #得到小于6的个数
8
np.sum(x < 6) # 等效于统计满足条件的个数
8
sum有一个优于count_nonzero的作用,可以沿着维度操作:
np.sum(x < 6, axis=0) # 和一定是8
array([2, 2, 2, 2])
np.sum(x < 6, axis=1) # 和一定是8
array([4, 2, 2])
np.all(x < 8) # 是否所有的值都小于8
False
np.all(x < 8, axis=1) # any也可以这样操作
array([ True, False, True])
ps: 可以利用通用函数对布尔数组操作,灵活操作可以很方便的处理和理解数据。
位操作符在布尔数组中的复合表达式
np.sum((inches > 0.5) & (inches < 1))
29
上面表达式的含义:降水量在0.5~1之间的天数是29天。
# 同理 A AND B == NOT(NOT A OR NOT B)
np.sum(~( (inches <= 0.5) | (inches >= 1) ))
29
形象的逻辑表达数据
# 所有下雨天用布尔数组标记起来
rainy = inches > 0
# 构建一个包含夏季的布尔数组(6月21日是第172天)
summer = ((np.arange(365) - 172) > 0) & ((np.arange(365) - 172) < 90)
print("全年雨量数据的中位数:", np.median(inches))
print("下雨天雨量数据的中位数是: ", np.median(inches[rainy]))
print("夏天雨量数据的中位数是:", np.median(inches[summer]))
print("夏天雨量最大是:", np.max(inches[summer]))
print("非夏季下雨天雨量中位数:", np.median(inches[~summer & rainy]))
全年雨量数据的中位数: 0.0
下雨天雨量数据的中位数是: 0.19488188976377951
夏天雨量数据的中位数是: 0.0
夏天雨量最大是: 0.8503937007874016
非夏季下雨天雨量中位数: 0.20078740157480315