
上QQ阅读APP看书,第一时间看更新
2.2.5 ufunc的方法
ufunc函数对象本身还有一些方法函数,这些方法只对两个输入、一个输出的ufunc函数有效,其他的ufunc对象调用这些方法时会抛出ValueError异常。
reduce()方法和Python的reduce()函数类似,它沿着axis参数指定的轴对数组进行操作,相当于将<op>运算符插入到沿axis轴的所有元素之间:<op>.reduce(array, axis=0, dtype=None)。例如:
r1 = np.add.reduce([1, 2, 3]) # 1 + 2 + 3 r2 = np.add.reduce([[1, 2, 3], [4, 5, 6]], axis=1) # (1+2+3),(4+5+6) r1 r2 -- -------- 6 [ 6, 15]
accumulate()方法和reduce()类似,只是它返回的数组和输入数组的形状相同,保存所有的中间计算结果:
a1 = np.add.accumulate([1, 2, 3]) a2 = np.add.accumulate([[1, 2, 3], [4, 5, 6]], axis=1) a1 a2 --------- -------------- [1, 3, 6] [[ 1, 3, 6], [ 4, 9, 15]]
reduceat()方法计算多组reduce()的结果,通过indices参数指定一系列的起始和终止位置。它的计算有些特别,让我们通过例子详细解释一下:
a = np.array([1, 2, 3, 4]) result = np.add.reduceat(a, indices=[0, 1, 0, 2, 0, 3, 0]) result array([ 1, 2, 3, 3, 6, 4, 10])
对于indices参数中的每个元素都会计算出一个值,因此最终的计算结果和indices参数的长度相同。结果数组result中除最后一个元素之外,都按照如下计算得出:
if indices[i] < indices[i+1]: result[i] = <op>.reduce(a[indices[i]:indices[i+1]]) else: result[i] = a[indices[i]]
而最后一个元素如下计算:
<op>.reduce(a[indices[-1]:])
因此在上面的例子中,数组result的每个元素按照如下计算得出:
1 : a[0] -> 1 2 : a[1] -> 2 3 : a[0] + a[1] -> 1 + 2 3 : a[2] -> 3 6 : a[0] + a[1] + a[2] -> 1 + 2 + 3 = 6 4 : a[3] -> 4 10: a[0] + a[1] + a[2] + a[4] -> 1 + 2 + 3 + 4 = 10
可以看出result[::2]和a相等,而result[1::2]和np.add.accumulate(a)相等。
ufunc函数对象的outer()方法等同于如下程序:
a.shape += (1,)*b.ndim <op>(a,b) a = a.squeeze()
其中squeeze()方法剔除数组a中长度为1的轴。让我们看一个例子:
np.multiply.outer([1, 2, 3, 4, 5], [2, 3, 4]) array([[ 2, 3, 4], [ 4, 6, 8], [ 6, 9, 12], [ 8, 12, 16], [10, 15, 20]])
可以看出通过outer()计算的结果是如下乘法表:
*| 2 3 4 ------------ 1| 2 3 4 2| 4 6 8 3| 6 9 12 4| 8 12 16 5|10 15 20
如果将这两个数组按照等同程序一步一步地进行计算,就会发现乘法表最终是通过广播的方式计算出来的。