2020-01-22 17:01:00
全文共3384字,预计学习时长10分钟
图源:Unsplash
Python初学者除了要掌握基础知识外,了解一些小技巧、小窍门也是学习路上必不可少的一种催化剂,能帮助你更好的学习。
Numpy作为Python最受欢迎的库之一,鉴于其优势,几乎每个Python程序员都将其用于算术运算。Numpy数组比Python列表更紧凑。该库还方便地以非常高效的计算方式实现了许多常见的矩阵运算。
下面小芯就基于实践整理出了Python初学者应该学习的4个numpy技巧,它们能够帮助你编写更简洁易读的代码。
在学习numpy技巧之前,请确保已熟悉以下文章中的一些Python内置功能。
数据集是不完善的,它们总是包含缺失或无效记录的数组,而这些记录是时常需要忽略的。例如,由于传感器故障,气象站的测量值可能包含缺失值。
Numpy有一个子模块numpy.ma,它支持带掩码的数据数组。带掩码的数组包含一个普通的numpy数组和一个指示无效记录位置的掩码。
np.ma.MaskedArray(data=arr,mask=invalid_mask)
有时使用负值或字符串标记数组中的无效记录。如果知道被掩盖的值,例如-999,也可以使用np.ma.masked_values(arr,value = -999)创建一个掩码数组。任何以掩码数组为参数的numpy操作都会自动忽略这些无效记录,如下所示。
import math
defis_prime(n):
assert n >1, 'Input must be larger than 1'
if n %2==0and n >2:
returnFalse
returnall(n % i for i inrange(3, int(math.sqrt(n)) +1, 2))
arr = np.array(range(2,100))
non_prime_mask = [not is_prime(n) for n in a]
prime_arr = np.ma.MaskedArray(data=arr, mask=non_prime_mask)
print(prime_arr)
# [2 3 -- 5 -- 7 -- -- -- 11 -- 13 -- --
-- 17 -- 19 -- -- -- 23 -- -- -- --
# -- 29 -- 31 -- -- -- -- -- 37 -- --
-- 41 -- 43 -- -- -- 47 -- -- -- --
# -- 53 -- -- -- -- -- 59 -- 61 -- --
-- -- -- 67 -- -- -- 71 -- 73 -- --
# -- -- -- 79 -- -- -- 83 -- -- -- --
-- 89 -- -- -- -- -- -- -- 97 -- --]
arr = np.array(range(11))
print(arr.sum()) # 55
arr[-1] =-999# indicates missing value
masked_arr = np.ma.masked_values(arr, -999)
print(masked_arr.sum()) # 45
查看由GitHub托管在❤的rawnumpy-ma.py
图源:Unsplash
广播是一个numpy初学者可能会不经意尝试过的事情。许多numpy算术运算都应用在具有相同形状的数组对上,并对这些数组对的元素进行逐一操作。广播可以向量化数组操作,而无需复制不必要的数据。这带来了有效的算法实现和更高的代码可读性。
例如,可以使用arr + 1将数组中的所有值加1,而不考虑arr的维数。还可以通过arr > 2检查数组中的所有值是否都大于2。
但是如何知道两个数组是否与广播兼容呢?
Argument 1 (4D array): 7× 5 × 3 × 1
Argument 2 (3D array): 1 × 3 × 9
Output (4D array): 7 × 5 × 3 × 9
两个数组的每个维度必须相等,或者其中之一为1。它们不需要具有相同数量的维度。以上示例说明了这些规则。
对于一个数组arr,np.argmax(arr),np.argmin(arr)以及np.argwhere(condition(arr))分别返回最大值,最小值以及满足用户定义条件的值的索引。尽管这些arg函数得到了广泛使用,但我们经常忽略np.argsort()函数,它用于返回对数组进行排序的索引。
可以使用np.argsort根据另一个数组对数组的值进行排序。以下示例使用考试分数对学生姓名进行排序。也可以使用np.argsort(np.argsort(score))将排序后的姓名数组转换回其原始顺序。
score = np.array([70, 60, 50, 10, 90, 40, 80])
name = np.array(['Ada', 'Ben', 'Charlie', 'Danny',
'Eden', 'Fanny', 'George'])
sorted_name = name[np.argsort(score)]
# an array of names in ascending order of their scores
print(sorted_name)
# ['Danny' 'Fanny' 'Charlie' 'Ben' 'Ada' 'George' 'Eden']
original_name = sorted_name[np.argsort(np.argsort(score))]
print(original_name)
# ['Ada' 'Ben' 'Charlie' 'Danny' 'Eden' 'Fanny' 'George']
%timeit name[np.argsort(score)]
# 1.83 µs ± 182 ns per loop
(mean ± std. dev. of 7 runs, 100000 loops each)
%timeit sorted(zip(score, name))
# 3.2 µs ± 76.7 ns per loop
(mean ± std. dev. of 7 runs, 100000 loops each)
查看由GitHub托管在❤ 的rawnumpy-argsort.py
它的性能比使用内置的Python函数sorted(zip())快,并且可读性更高。
图源:Unsplash
分割numpy数组的语法为i:j,其中i,j分别代表起始索引和终止索引。对于一个numpy数组arr=np.array(range(10)),调用arr[:3]即返回[0,1,2]。
当处理高维数组时,可以使用: 来选择每个轴的所有索引。还可以使用…选择多个轴上的所有索引。由此可以推断出扩展轴的确切数量。
arr = np.array(range(1000)).reshape(2,5,2,10,-1)
print(arr[:,:,:,3,2] == arr[...,3,2])
# [[[ True, True],
# [ True, True],
# [ True, True],
# [ True, True],
# [ True, True]],
# [[ True, True],
# [ True, True],
# [ True, True],
# [ True, True],
# [ True, True]]])
print(arr.shape) # (2, 5, 2, 10, 5)
print(arr[...,np.newaxis,:,:,:].shape) # (2, 5, 1, 2, 10, 5)
查看由GitHub托管在❤的rawnumpy-slicing.py
另一方面,如上所示使用np.newaxis在用户定义的轴位置插入新轴。此操作将数组的形状扩展了一个维度单位。尽管这也可以通过np.expand_dims()实现,但使用np.newaxis更具可读性,并且更加优雅。
图源:Unsplash
祝大家继续开心敲代码~一天更比一天强~