上回说到这本书的第二章 Python One-Liners(1)
这回来到第三章,是关于 Data Science 的一行代码(这里写其中一个)
有一个 (4, 6) 的二维数组 X,每行代表一个城市的空气质量指数 ( AQI )
import numpy as np
## AQI data, row=city 行:城市
X = np.array([[42,40,41,43,44,43], # Hong Kong
[30,31,29,29,29,30], # New york
[8,13,31,11,11,9], # Berlin
[11,11,12,13,11,12]]) # Montreal
cities = np.array(['HongKong','Newyork','Berlin','Montreal'])
问题:找出这几个城市中空气质量指数大于平均值的城市。
先给结果:
## One-Liner
polluted = set(cities[np.nonzero(X > np.average(X))[0]])
# 输出结果:
print(polluted)
# {'Berlin', 'HongKong', 'Newyork'}
How It Works?
我们从里到外一步一步拆解
np.average() 用于求 X 的平均值
np.average(X)
## 24.333333333333332
X > np.average(X) 会得到一个布尔值组成的二维数组,即,用X中的每一个元素和平均值比较大小,这里涉及到 Numpy 的广播机制(Broadcast),大则为True, 小则为False
X > np.average(X) # 判断 X 的元素哪些大于平均值
## 结果如下:
array([[ True, True, True, True, True, True],
[ True, True, True, True, True, True],
[False, False, True, False, False, False],
[False, False, False, False, False, False]])
np.nonzero()的输入参数为数组,返回值为相应数组中非零元素的下标数组,输入的数组是几维的,则输出相应个数的数组组成的tuple,看下面的例子更加直观:
# 一维数组
np.nonzero([1,0,2])
# 结果: 第0个和第2个下标(索引)对应的元素非0
(array([0, 2], dtype=int64),)
# 布尔值组成的一维数组
np.nonzero([True,True,False,True])
# 结果: 第0,1,3个元素为True,则输出相应下标组成的数组
(array([0, 1, 3], dtype=int64),)
# 二维数组
np.nonzero([[1,2,0],
[0,0,3]])
# 结果 :分别是下标为[0,0]的1,下标为[0,1]的2,下标为[1,2]的3非零
# 所以输出了第一维的下标[0,0,1]和第二维的下标[0, 1, 2]组成的tuple
(array([0, 0, 1], dtype=int64),
array([0, 1, 2], dtype=int64))
# 三维数组依此类推
np.nonzero([[[1,2,0],[0,0,3]],
[[0,4,0],[0,5,0]]])
# 结果:
(array([0, 0, 0, 1, 1], dtype=int64),
array([0, 0, 1, 0, 1], dtype=int64),
array([0, 1, 2, 1, 1], dtype=int64))
那么,回到这个问题,是对布尔值组成的二维数组进行 nonzero() 计算
np.nonzero(X > np.average(X))
# 得到结果:
(array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2], dtype=int64),
array([0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 2], dtype=int64))
对于二维数组,可以这样理解,nonzero() 返回的 tuple 中,第0个数组代表的是行索引(下标),第1个数组代表的是列索引。
取得行索引:
np.nonzero(X > np.average(X))[0]
## 取得行索引结果
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2], dtype=int64)
由于题目的数据中,每一行代表一个城市,可以通过行索引,在 cities 中找到对应的城市,也就是:
cities[np.nonzero(X > np.average(X))[0]]
## 结果:
## array(['HongKong', 'HongKong', 'HongKong',
'HongKong', 'HongKong', 'HongKong',
'Newyork', 'Newyork', 'Newyork',
'Newyork', 'Newyork','Newyork',
'Berlin'], dtype='<U8')
再通过 set()对上面的结果集进行去重处理,得到最终结果
set(cities[np.nonzero(X > np.average(X))[0]])
# 结果:
{'Berlin', 'HongKong', 'Newyork'}
知识点总结及参考链接:
numpy.average()
https://www.runoob.com/numpy/numpy-statistical-functions.html
https://numpy.org/devdocs/reference/generated/numpy.average.html#numpy.average
numpy.nonzero()
https://www.runoob.com/numpy/numpy-sort-search.html
numpy-Broadcasting
https://www.runoob.com/numpy/numpy-broadcast.html
https://www.numpy.org.cn/article/basics/python_numpy_tutorial.html#%E5%B9%BF%E6%92%AD-broadcasting
Python.set()
https://www.runoob.com/python/python-func-set.html
感谢你的阅读,希望有所收获。
网友评论