Python 高阶ufunc用法


高阶ufunc用法

虽然许多NumPy用户只会使用通用函数提供的按元素操作,但还有一些额外的功能偶尔可以帮助编写更简洁的代码而无须循环。

1、ufunc实例方法

NumPy的每个二元ufunc(通用函数)都有特殊的方法来执行某些特殊的向量化操作。表A-2总结了这些内容,但我将举几个具体示例来说明它们的工作原理。

reduce方法接收单个数组并通过执行一系列二元操作在可选的轴向上对数组的值进行聚合。例如,使用np.add.reduce是对数组中元素进行加和的另一种方法:

起始值(对于add方法是0)取决于ufunc。如果传递了一个轴,则沿该轴执行缩聚。这使你能够以简洁的方式回答某些种类的问题。可以使用np.logical_and来检查数组的每一行中的值是否被排序:

accumulate与reduce是相关的,就像cumsum与sum相关一样。accumulate生成一个数组,其尺寸与中间“累计”值相同:

outer在两个数组之间执行成对的交叉乘积:

outer的输出的维度等于输入的维度总和:

最后一个方法reduceat执行“本地缩聚”,本质上是一个数组groupby操作,在操作中数组的切片聚合在了一起。reduceat方法接受一系列的“箱体边缘”,这些箱体边缘表示如何分隔以及聚合数据值:

结果是在arr[0:5]、arr[5:8]和arr[8:]上执行了缩聚(此处是加和)。在其他方法中,可以传递一个axis参数:

下表列出了部分ufunc方法。

2、使用Python编写新的ufunc方法

有很多工具可以用于创建你自己的NumPy ufunc,最常用的是NumPy的C语言API。 numpy.frompyfunc函数接收一个具有特定数字输入和输出的函数。例如,一个简单的按元素相加的函数可以如下:

使用frompyfunc创建的函数通常返回的是Python对象的数组,这并不方便。幸运的是,还有另一个函数numpy.vectorize允许指定输出的类型(但功能稍差):

这些函数提供了一种创建类似ufunc的函数的方法,但是它们非常慢,因为它们需要Python函数调用来计算每个元素,这比NumPy的基于C的ufunc循环要慢很多: