「Python数据科学」利用NumPy通用函数ufunc进行面向数组编程

南宫理的日志录 2025-01-03 08:15:24
引言

NumPy中的多维数组ndarray,使得我们可以将许多数据处理任务,表述为更加简洁的数组表达式,而无需编写Python循环。用数组表达式代替循环的做法通常称为向量化。

通常来说,向量化数组运算要比等价的纯Python方式快得多。本文就来结合之前已经介绍过的内容,对利用NumPy进行面向数组编程进行系统的介绍,并补充上关于通用函数ufunc的内容。

本文的主要内容有:

1、NumPy面向数组编程的核心特性

2、通用函数ufunc

3、自定义ufunc

NumPy面向数组编程的核心特性

NumPy中提供了多种特性,用以支持面向数组编程,最终实现基于数组表达式,轻松实现各种科学计算的应用场景。

NumPy中关于面向数组编程的核心特性主要有:

1、N维数组对象(ndarray)

ndarray是一个多维数组,只能存储相同类型的数据,使得数组计算的向量化变得更加合理。

2、向量化(vectorization)

向量化是将操作应用于整个数组而不是单个元素的过程。

这种方法通常比使用Python循环更加简洁且高效,因为NumPy底层使用了C语言实现的优化代码。

3、广播(broadcasting)

广播是NumPy的一项强大功能,它突破了不同形状数组无法直接计算的限制。

对于符合相关规则的数组,NumPy会自动进行扩展,使得参与运算的数组各自扩展维相同的形状,减少了我们需要手动调整数组形状的工作量,大大提高了编码的效率。

4、通用函数(ufuncs)

NumPy提供了许多通用函数,用于对数组进行逐元素操作,比如各种数学运算、逻辑运算等。这些函数通常会作用域每个元素,效率很高。

关于以上这些特性,除了通用函数,其他内容在前面的文章中都已经详细介绍,感兴趣的同学,可以自行查阅历史文章。

接下来,就对通用函数的内容做一个系统的介绍。

通用函数ufunc

在NumPy中,通用函数(Universal Function, ufunc)是一种能够对数组中的元素进行逐元素操作的函数。

它是NumPy中的核心特性之一,旨在高效地执行数组运算。

ufunc可以用于执行各种数学运算,比如加法、减法、乘法、除法等,以及更加复杂的操作。

ufunc的底层基于两个核心特性实现:

1、逐元素(element-by-element)操作,ufunc可以对输入数组的每个元素进行操作,并返回一个输出数组,输出数组的形状由输入数组的形状决定。

2、广播机制,ufunc依赖广播机制,可以实现对不同形状的数组进行逐元素的运算。

下面,通过代码简单演示下NumPy中的ufunc:

NumPy中提供的通用函数,根据参数,可以分为:一元通用函数和二元通用函数。

常见的一元通用函数有:

常用的二元通用函数有:

自定义ufunc

除了使用NumPy中内置的ufunc,我们也可以根据需要,自行创建ufunc。

NumPy中的np.frompyfunc()函数,可以支持我们将自定义函数转换为通用函数,从而实现逐元素计算的功能。

通过代码简单演示自定义ufunc的方法:

这里主要用到了np.frompyfunc()函数:

调用该函数时,依次传入的参数为:自定义的Python函数名、函数参数个数、函数返回值个数。

但是,使用np.frompyfunc()函数获得的ufunc返回的数组元素类型都是object,这点不太方便。

这一点,可以通过np.vectorize类来解决:

使用np.vectorize类进行包装,获取一个可调用对象,实现向量化操作。

通过代码简单演示一下:

但是,需要注意的是,相对于内置的通用函数,自定义的ufunc,会比较慢,因为在计算每个元素时,都要执行一次Python函数调用!

如果对自定义的ufunc的性能有所要求,可以尝试使用Numba库来进行进一步的性能提升。

下面同样通过代码简单演示下通过Numba库实现向量化的方法:

关于性能的对比,以及Numba库的使用,感兴趣的同学可以自行进行深入研究。

总结

本文首先简单回顾了ndarray、向量化、广播的相关内容。然后,介绍了基于NumPy中的核心特性:ndarray、向量化、广播,以及ufunc实现面向数组编程的方法。最后介绍了内置ufunc的使用,以及如何自定义ufunc的3种方法。

以上就是本文的全部内容,感谢您的拨冗阅读!

0 阅读:4
南宫理的日志录

南宫理的日志录

深耕IT科技,探索技术与人文的交集