工具-numpy
numpy是使用Python进行数据科学的基础库。numpy以一个强大的N维数组对象为中心,它还包含有用的线性代数,傅里叶变换和随机数函数。
算术运算
导入numpy
import numpy as np
所有常用的算术运算+,-,*,/,//,%,**等等,都可以应用在ndarray上,且这些运算是方面级的。
a = np.array([14, 23, 32, 4])
b = np.array([5, 4, 3, 2])
print('a + b =', a + b)
print('a - b =', a - b)
print('a * b =', a * b)
print('a / b =', a / b)
print('a // b =', a // b)
print('a % b =', a % b)
print('a ** b =', a ** b)
输出:
a + b = [19 27 35 6]
a - b = [ 9 19 29 2]
a * b = [70 92 96 8]
a / b = [ 2.8 5.75 10.66666667 2. ]
a // b = [ 2 5 10 2]
a % b = [4 3 2 0]
a ** b = [537824 279841 32768 16]
需要注意的是,上面的乘法运算不是矩阵乘法,下面会介绍矩阵乘法。
上面算术运算的前提是ndarray必须有一样的形状,否则numpy将会应用广播机制。
广播
第一条规则
当ndarray没有相同的秩时,那么将为秩较小ndarray的形状数组上加入1,直到他们的秩匹配为止。
h = np.arange(5).reshape(1, 1, 5)
h
输出:
array([[[0, 1, 2, 3, 4]]])
现在尝试将一个形状为(5,)的一维数组加到这个形状为(1,1,5)的三维数组上,遵循第一条广播规则,结果如下:
h + np.array([10, 20, 30, 40, 50])
输出:
array([[[10, 21, 32, 43, 54]]])
第二条规则
在特定维度为1的数组,沿着该维度将元素的值进行重复,直到和在该维度上拥有最大形状的ndarray大小相同为止。
k = np.arange(6).reshape(2, 3)
k
输出:
array([[0, 1, 2],
[3, 4, 5]])
现在让一个形状为(2,1)的二维ndarray加到形状为(2, 3)的二维数组上,numpy将会应用第二条广播规则。
k + np.array([[100], [200]])
输出:
array([[100, 101, 102],
[203, 204, 205]])
结合规则1和规则2:
k + np.array([100, 200, 300])
输出:
array([[100, 201, 302],
[103, 204, 305]])
k + 1000
输出:
array([[1000, 1001, 1002],
[1003, 1004, 1005]])
第三条规则
在规则1和规则2之后,第三条规则是所有数组的大小必须匹配,如下
try:
k + [33, 44]
except ValueError as e:
print(e)
operands could not be broadcast together with shapes (2,3) (2,)
广播规则用于许多numpy运算,不仅仅是算术运算,下面会介绍。
Upcasting
当尝试组合具有不同数据类型的ndarray时,numpy将向上转换为更通用或精确度更高的数据类型,无论实际值是什么。
k1 = np.arange(0, 5, dtype=np.uint8)
print(k1.dtype, k1)
输出:
uint8 [0 1 2 3 4]
k2 = k1 + np.array([5, 6, 7, 8, 9], dtype=np.int8)
print(k2.dtype, k2)
输出:
int16 [ 5 7 9 11 13]
上面这种情况尽管uint8就足够了,但是需要使用int16来表示所有可能的int8和uint8值(从-128到255)。
k3 = k1 + 1.5
print(k3.dtype, k3)
输出:
float64 [1.5 2.5 3.5 4.5 5.5]
条件运算
条件运算也适用于元素
m = np.array([20, -5, 30, 40])
m < [15, 16, 35, 36]
输出:
array([False, True, True, False])
m < 25
输出:
array([ True, True, False, False])
这与布尔索引结合起来使用非常有用。
m[m < 25]
输出:
array([20, -5])
数学和统计函数
许多数学和统计函数也适用于ndarray。
ndarray的方法
一些函数仅仅是ndarray的方法,例如:
a = np.array([[-2.5, 3.1, 7], [10, 11, 12]])
print(a)
print("mean = ", a.mean())
输出:
[[-2.5 3.1 7. ]
[10. 11. 12. ]]
mean = 6.766666666666667
不管ndarray的形状如何,mean()函数将会计算ndarray中所有元素的平均值。
这有一些更实用的ndarray方法
for func in (a.min, a.max, a.sum, a.prod, a.std, a.var):
print(func.__name__, '=', func())
输出:
min = -2.5
max = 12.0
sum = 40.6
prod = -71610.0
std = 5.084835843520964
var = 25.855555555555554
这些函数可以接受一个可选参数axis,该参数允许对给定轴上的元素执行操作。例如:
c = np.arange(24).reshape(2, 3, 4)
c
输出:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
c.sum(axis=0)
输出:
array([[12, 14, 16, 18],
[20, 22, 24, 26],
[28, 30, 32, 34]])
c.sum(axis=1)
输出:
array([[12, 15, 18, 21],
[48, 51, 54, 57]])
c.sum(axis=2)
输出:
array([[ 6, 22, 38],
[54, 70, 86]])
也可以在多个轴上求和
c.sum(axis=(0, 2))
输出:
array([ 60, 92, 124])
通用函数
numpy还提供了快速的元素级函数,它们被称为通用函数或ufunc。它们是简单函数的矢量化包装。例如,square返回一个新ndarray,它是原始ndarray的副本,但每个元素是原来元素的平方。
a = np.array([[-2.5, 3.1, 7], [10, 11, 12]])
np.square(a)
输出:
array([[ 6.25, 9.61, 49. ],
[100. , 121. , 144. ]])
还有一些更实用的一元通用函数。
print('Original ndarray')
print(a)
for func in (np.abs, np.sqrt, np.exp, np.log, np.sign, np.ceil, np.modf, np.isnan, np.cos):
print('\n', func.__name__)
print(func(a))
输出:
Original ndarray
[[-2.5 3.1 7. ]
[10. 11. 12. ]]
absolute
[[ 2.5 3.1 7. ]
[10. 11. 12. ]]
sqrt
[[ nan 1.76068169 2.64575131]
[3.16227766 3.31662479 3.46410162]]
exp
[[8.20849986e-02 2.21979513e+01 1.09663316e+03]
[2.20264658e+04 5.98741417e+04 1.62754791e+05]]
log
[[ nan 1.13140211 1.94591015]
[2.30258509 2.39789527 2.48490665]]
sign
[[-1. 1. 1.]
[ 1. 1. 1.]]
ceil
[[-2. 4. 7.]
[10. 11. 12.]]
modf
(array([[-0.5, 0.1, 0. ],
[ 0. , 0. , 0. ]]), array([[-2., 3., 7.],
[10., 11., 12.]]))
isnan
[[False False False]
[False False False]]
cos
[[-0.80114362 -0.99913515 0.75390225]
[-0.83907153 0.0044257 0.84385396]]
二元通用函数
还有许多二元通用函数,它们在两个ndarray上按元素应用,如果ndarray形状不同,则应用广播规则。
a = np.array([1, -2, 3, 4])
b = np.array([2, 8, -1, 7])
np.add(a, b)
输出:
array([ 3, 6, 2, 11])
np.greater(a, b)
输出:
array([False, False, True, False])
np.maximum(a, b)
输出:
array([2, 8, 3, 7])
np.copysign(a, b)
输出:
array([ 1., 2., -3., 4.])
|