跳转至

8.8.ufunc函数

import numpy as np
np.set_printoptions(threshold=40)
Linux 5.4.0-74-generic
Python 3.9.5 @ GCC 7.3.0
Latest build date 2021.06.16
numpy version:  1.20.3

通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数。可以将其看做简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器。

  • 一元(unary)ufunc:接受1个数组的输入。

  • 二元(binary)ufunc:接受2个数组的输入。

四则运算

a = np.arange(1, 6)
b = np.arange(5, 10)

# 表达式形式
a + a
a - a
a * a # 元素相乘
a / a
b // a # 取整除法
b % a # 取模

# ufunc函数形式
np.add(a, a)
np.subtract(a, a)
np.multiply(a, a)  # 元素相乘
## 在python3 divide、true_divide没有差别
np.true_divide(b, a)
np.divide(b, a)
## 相当于先调用divide函数 再调用floor函数
np.floor_divide(b, a)  # 取整除法
np.mod(b, a)  # 元素级求模
array([0, 0, 1, 0, 4])

比较运算

a = np.arange(20).reshape(2,10)
b = np.arange(10,30).reshape(2,10)

# 表达式形式
a == b
a != b
a < b
a <= b
a > b
a >= b

# ufunc函数形式
np.equal(a,b)
np.not_equal(a,b)
np.less(a,b)
np.less_equal(a,b)
np.greater(a,b)
np.greater_equal(a,b)
array([[False, False, False, False, False, False, False, False, False,
        False],
       [False, False, False, False, False, False, False, False, False,
        False]])

逻辑运算

a = np.arange(20).reshape(2, 10)
b = np.arange(10, 30).reshape(2, 10)

# 与
np.logical_and(a, b)
# 或
np.logical_or(a, b)
# 非
np.logical_not(b)
# 异或
np.logical_xor(a, b)
# 任意一个元素
np.any(a)
# 全部元素
np.all(a)
False

位运算

a = np.arange(20).reshape(2, 10)
b = np.arange(10, 30).reshape(2, 10)

a & b
a | b
~a
a^b

# 按位与
np.bitwise_and(a, b)
# 按位或
np.bitwise_or(a, b)
# 按位取反
np.bitwise_not(a)
# 按位异或
np.bitwise_xor(a, b)
array([[10, 10, 14, 14, 10, 10, 22, 22, 26, 26],
       [30, 30, 26, 26, 22, 22, 10, 10, 14, 14]])

自定义 ufunc 函数

可以通过frompyfunc()将计算单个元素的函数转换成ufunc函数。调用格式为如下:

numpy.frompyfunc(func, nin, nout)

# func:计算单个元素的函数
# nin:func的输入参数的个数 The number of input
# nout:func返回值的个数 The number of output
def my_add(x, y):
    z = x + y + 1
    return z

myufunc = np.frompyfunc(my_add, 2, 1)

a = np.arange(5)
b = np.arange(5,10)
myufunc(a, b)
array([6, 8, 10, 12, 14], dtype=object)

也可以通过vectorize()函数来实现frompyfunc()的功能。

np.vectorize(func, otypes='', doc=None, excluded=None)

# func:计算单个元素的函数
# otypes:可以是一个表示结果数组元素类型的字符串,也可以是一个类型列表。如果使用类型列表,可以描述多个返回数组的元素类型
# doc:函数的描述字符串。若未给定,则使用func.__doc__
# excluded:指定func中哪些参数未被向量化。你可以指定一个字符串和整数的集合,其中字符串代表关键字参数,整数代表位置参数。
a = np.arange(5)
b = np.arange(5,10)

def my_add(x, num):
    z = x + num
    return z

myufunc = np.vectorize(my_add, doc="每一个元素加上一个指定的数")
print(myufunc.__doc__)
myufunc(a, 1)
每一个元素加上一个指定的数
array([1, 2, 3, 4, 5])
def my_add(x, y, list_num):
    z = x + y
    for i in list_num:
        z = z + i
    return z

myufunc = np.vectorize(my_add, excluded=[2])
myufunc(a, b, [1, 2, 3])  # list_num 作为一个list,而不是向量化成一个个元素
array([11, 13, 15, 17, 19])
def my_add(x, num):
    z = x + num
    return z, z

myufunc = np.vectorize(my_add, otypes=[np.float, int])
myufunc(a, 1)
<ipython-input-1-4753d7c47f71>:5: DeprecationWarning: `np.float` is a
deprecated alias for the builtin `float`. To silence this warning, use
`float` by itself. Doing this will not modify any behavior and is
safe. If you specifically wanted the numpy scalar type, use
`np.float64` here.
Deprecated in NumPy 1.20; for more details and guidance:
https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  myufunc = np.vectorize(my_add, otypes=[np.float, int])
(array([1., 2., 3., 4., 5.]), array([1, 2, 3, 4, 5]))

ufunc 对象的方法

ufunc函数对象本身还有一些方法。

这些方法只对于两个输入、一个输出的ufunc函数函数有效。对于其他的ufunc函数对象调用这些方法时,会抛出ValueError异常。

ufunc.reduce()

ufunc.reduce方法:类似于Python的reduce函数,它==沿着==axis参数指定的轴,对数组进行操作。经过一次reduce,结果数组的维度降低一维。

假设<op>是一个ufunc函数,ufunc.reduce用法如下:

<op>.reduce(array,axis=0,dtype=None)
a = np.arange(20).reshape(5, 4)
print(a)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
np.add.reduce(a, axis=1)  # 沿着 列方向
array([ 6, 22, 38, 54, 70])
np.add.reduce(a, axis=0)  # 沿着 行方向
array([40, 45, 50, 55])

相当于将运算符插入到沿着axis轴的所有元素之间:

a = np.arange(20).reshape(5, 4)
print(a)

def fun(a,b):
    z = a + b + 1
    return z

fun2 = np.frompyfunc(fun, 2, 1)
fun2.reduce(a, axis=1)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
array([9, 25, 41, 57, 73], dtype=object)

ufunc.accumulate()

ufunc.accumulate方法:它类似于reduce()的计算过程,但是它会保存所有的中间计算结果,从而使得返回数组的形状和输入数组的形状相同:

a = np.arange(20).reshape(5, 4)
print(a)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
np.add.accumulate(a, axis=1)
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38],
       [12, 25, 39, 54],
       [16, 33, 51, 70]])

ufunc.outer()

ufunc.outer方法:相当于将运算符对输入数组A和输入数组B的每一对元素对(a,b)起作用。设A的shape=(4,5),B的shape为(4,),则结果数组的shape=(4,5,4)

一维数组和一维数组的outer操作为二维数组

a = np.arange(1, 6)
b = np.arange(1, 5)
np.add.outer(a, b)
array([[2, 3, 4, 5],
       [3, 4, 5, 6],
       [4, 5, 6, 7],
       [5, 6, 7, 8],
       [6, 7, 8, 9]])

多维数组的outer拆分成各自的一维操作

a = np.arange(1, 7).reshape(2, 3)
b = np.arange(1, 5)
np.add.outer(a, b)
array([[[ 2,  3,  4,  5],
        [ 3,  4,  5,  6],
        [ 4,  5,  6,  7]],

       [[ 5,  6,  7,  8],
        [ 6,  7,  8,  9],
        [ 7,  8,  9, 10]]])

数学函数

下面是一元的数学函数:

  1. abs/fabs:计算整数、浮点数或者复数的绝对值。对于非复数值,可以使用更快的fabs

  2. sqrt:计算平方根,相当于$a^{0.5}$

  3. square:计算平方,相当于$a^2$

  4. exp:计算指数$e^x$

  5. log/log10/log2/log1p:分别为$log_{e}(a), log_{10}(a), log_2(a), log_e(1+x)$

  6. sign:计算$sign(a)$

  7. ceil:计算各元素的ceiling值:大于等于该值的最小整数

  8. floor:计算个元素的floor值:小于等于该值的最大整数

  9. rint:将各元素四舍五入到最接近的整数,保留dtype

  10. modf:将数组的小数和整数部分以两个独立数组的形式返回

  11. cos/cosh/sin/sinh/tan/tanh:普通和双曲型三角函数

  12. arccos/arcsosh/arcsin/arcsinh/arctan/arctanh:反三角函数

  13. isnan:返回一个布尔数组,该数组指示那些是NaN

  14. isfinite/isinf:返回一个布尔数组,该数组指示哪些是有限的/无限数

统计函数

方法 说明
sum 对数组中全部或某轴向的元素求和。零长度的数组的sum为0
mean 算术平均数。零长度的数组的mean为NaN
stdvar 分别为标准差和方差,自由度可调(默认为n)
minmax 最大值和最小值
argminargmax 分别为最大和最小元素的索引
cumsum 所有元素的累计和
cumprod 所有元素的累计积

以上函数有一些共同的参数:(a, axis=None, dtype=None, out=None)

  • axisNone 、整数、整数元组。按顺序对axis指定的轴进行计算。例如,指定所有的轴,最后则输出一个标量。

  • out:ndarray。将结果输出到该数组。它必须有与预期输出形状相同,但输出类型必要时将强制转换值。

集合运算

方法 说明
unique(x) 计算x中的唯一元素,并返回有序结果
intersect1d(x, y) 计算X和y中的公共元素,并返回有序结果
union1d(x, y) 计算X和y的并集,并返回有序结果
in1d(x,y) 得到一个表示“X的元素是否包含于y”的布尔型数组
setdiff1d(x, y) 集合的差,即元素在x中且不在y中
setxor1d(x, y) 集合的对称差,即存在于一个数组中但不同时存在于两个数组中的元素
a = np.arange(0, 5)
b = np.arange(3, 8)

print(np.unique(a))
print(np.intersect1d(a, b))
print(np.union1d(a, b))
print(np.in1d(a, b))
print(np.setdiff1d(a, b))
print(np.setxor1d(a, b))
[0 1 2 3 4]
[3 4]
[0 1 2 3 4 5 6 7]
[False False False  True  True]
[0 1 2]
[0 1 2 5 6 7]