Python One-Liners(2)

上回说到这本书的第二章 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'}

51

五一劳动节快乐

知识点总结及参考链接:

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

感谢你的阅读,希望有所收获。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值