介绍点高级的东西,numpy中的ufunc。
ufunc(universal function)能够作用于narray对象上的元素级函数,这些函数在对narray对象进行运算的速度比使用循环或者列表推导式要快很多。
numpy中的ufunc函数:
python 中的逻辑运算and、or、not 在numpy中均以以logical_开头。
ufunc方法
ufunc函数对象本身还有一些方法函数,这些方法只对两个输入、一个输出的ufunc 函数有效(1) reduce()沿着指定轴对数组进行操作,相当于将相应的操作放到该轴元素之间。
In [111]: arr = np.arange(10) In [112]: arr.add.reduce(45) In [113]: np.add.reduce(45) Out[113]: 45 In [114]: arr.sum() Out[114]: 45 In [115]: arr1 = np.arange(12).reshape(3,4) In [116]: arr1 Out[116]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) In [117]: np.add.reduce(arr1,axis=1) Out[117]: array([ 6, 22, 38]) In [118]: np.add.reduce(arr1,axis=0) Out[118]: array([12, 15, 18, 21])
In [119]: arr2 = np.random.rand(5,5)
In [120]: arr2
Out[120]:
array([[0.58105936, 0.11015212, 0.57964562, 0.26717349, 0.37098113],
[0.7986871 , 0.43831348, 0.23055509, 0.58390981, 0.26887167],
[0.09343173, 0.75975338, 0.10638202, 0.09400437, 0.36757053],
[0.31254715, 0.04461316, 0.18108053, 0.50666021, 0.85490671],
[0.62270897, 0.89847847, 0.02525792, 0.21699692, 0.4513596 ]])
In [122]: arr2[::2].sort(1)
In [123]: arr2
Out[123]:
array([[0.11015212, 0.26717349, 0.37098113, 0.57964562, 0.58105936],
[0.7986871 , 0.43831348, 0.23055509, 0.58390981, 0.26887167],
[0.09343173, 0.09400437, 0.10638202, 0.36757053, 0.75975338],
[0.31254715, 0.04461316, 0.18108053, 0.50666021, 0.85490671],
[0.02525792, 0.21699692, 0.4513596 , 0.62270897, 0.89847847]])
In [127]: arr2[:,:-1] < arr2[:,1:]
Out[127]:
array([[ True, True, True, True],
[False, False, True, False],
[ True, True, True, True],
[False, True, True, True],
[ True, True, True, True]])
In [128]: np.logical_and.reduce( arr2[:,:-1] < arr2[:,1:],axis=1) # 利用 np.logical_and 判断各行是否有序
Out[128]: array([ True, False, True, False, True])
(2) accumulate()和reduce()的关系就想cumsum 和sum 的关系,区别时是前者会保留中间结果:
In [130]: arr = np.arange(15).reshape((3, 5)) In [131]: np.add.accumulate(arr) Out[131]: array([[ 0, 1, 2, 3, 4], [ 5, 7, 9, 11, 13], [15, 18, 21, 24, 27]], dtype=int32)
(3) reduceat()方法用于部分reduce计算,通过indices参数指定一系列的起始和终止位置
In [136]: arr = np.arange(10)
In [137]: arr
Out[137]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [138]: np.add.reduceat(arr,[0,5,8])
Out[138]: array([10, 18, 17], dtype=int32)
(4) outer() 计算两个数组的交叉积
In [93]: arr = np.arange(3).repeat([1,2,2])
In [94]: arr
Out[94]: array([0, 1, 1, 2, 2])
In [95]: np.multiply.outer(arr,np.arange(5)) # arr的每一个元素与 np.arange(5) 所有元素相乘,组成一行
Out[95]:
array([[0, 0, 0, 0, 0],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 2, 4, 6, 8],
[0, 2, 4, 6, 8]])
In [97]: arr1 = np.random.randn(3,4)
In [98]: arr1
Out[98]:
array([[ 0.67543289, 0.36378869, 1.57406552, -0.82169794],
[-0.3987699 , 1.48855953, 2.18038345, -0.79266692],
[ 0.73946519, 1.15944744, -0.38277991, 1.35506805]])
In [99]: arr2 = np.random.randn(5)
In [100]: arr2
Out[100]: array([ 0.37966625, -0.27666319, -0.89753076, 1.76468965, -0.17493179])
In [101]: np.subtract.outer(arr1,arr2) # shape (3,4,5)
Out[101]:
array([[[ 0.29576664, 0.95209608, 1.57296365, -1.08925676,
0.85036468],
[-0.01587757, 0.64045188, 1.26131944, -1.40090097,
0.53872048],
[ 1.19439927, 1.85072872, 2.47159628, -0.19062413,.............
自定义 ufunc
除了numpy内置ufunc函数,用户也可以自定义的ufunc函数
1. 编写对单个数值计算的目的函数;
def add_elements(x, y): return x + y
2. 利用np.frompyfunc(func, nin, nout)将其转换为ufunc函数
func:自己编写的目的函数, nin: 参数个数 nout:返回值个数
In [105]: add_1 = np.frompyfunc(add_elements,2,1) In [106]: add_1(np.arange(4),np.arange(4)) Out[106]: array([0, 2, 4, 6], dtype=object)这里返回的结果是python的object类型,需要用astype()手动转换为目标类型。numpy.vectorize()也实现了和numpy.frompyfunc()一样的功能,但是它通过otypes指定返回值的类型,不用手动行转换。
In [107]: add_1 = np.vectorize(add_elements, otypes=[np.float64]) In [109]: add_1(np.arange(4),np.arange(4)) Out[109]: array([0., 2., 4., 6.])
自定义的ufunc在性能上不如内置的。