假设我们有一个用于创建numpy数组对象的numpy数组的函数:
randarr = lambda shape: np.random.randint(0, 10, shape)
get_numpy_array_obj = lambda shapes: \
np.array([randarr(shape) for shape in shapes])以及数组的定义大小:
shapes = [(2, 3), (3, 4), (4, 2)]由于数组的形状不同,numpy将其他数组视为对象。
现在,如果我们创建两个这样的数组
A = get_numpy_array_obj(shapes)
B = get_numpy_array_obj(shapes)做简单的操作,如+,-,**等不是问题,例如:
C = A * B - (A + B)**2当我想在tanh,exp等数组上应用numpy函数时,问题就出现了。
D = np.tanh(A)这将向我返回以下错误:
AttributeError: 'numpy.ndarray' object has no attribute 'tanh'我可以对每个数组逐个应用函数,如下所示
D = np.array([np.tanh(a) for a in A])我的想法是写更少的代码和更多的可读性。
此外,np.vectorize(np.tanh)(A)也无法正常工作。这将返回:
ValueError: setting an array element with a sequence.是否有其他可能的方法将numpy函数应用于numpy数组对象的数组?
发布于 2018-02-19 00:34:40
In [99]: arr = np.array([np.ones(ij) for ij in [(1,3),(2,4),(3,2)]])
In [100]: arr
Out[100]:
array([array([[1., 1., 1.]]),
array([[1., 1., 1., 1.],
[1., 1., 1., 1.]]),
array([[1., 1.],
[1., 1.],
[1., 1.]])], dtype=object)像'+‘这样的运算符之所以有效,是因为数组有相应的方法:
In [101]: arr[0].__add__
Out[101]: <method-wrapper '__add__' of numpy.ndarray object at 0xb64897a0>
In [102]: arr+arr
Out[102]:
array([array([[2., 2., 2.]]),
array([[2., 2., 2., 2.],
[2., 2., 2., 2.]]),
array([[2., 2.],
[2., 2.],
[2., 2.]])], dtype=object)但是像np.tanh这样的函数没有数组方法。
frompyfunc将数组的元素传递给您的函数并返回一个对象数据类型数组。通常这很痛苦,但在这种情况下,这正是我们想要的:
In [103]: np.frompyfunc(np.tan,1,1)(arr)
Out[103]:
array([array([[1.55740772, 1.55740772, 1.55740772]]),
array([[1.55740772, 1.55740772, 1.55740772, 1.55740772],
[1.55740772, 1.55740772, 1.55740772, 1.55740772]]),
array([[1.55740772, 1.55740772],
[1.55740772, 1.55740772],
[1.55740772, 1.55740772]])], dtype=object)vectorize也使用frompyfunc,但会尝试将结果转换为数字数组。我们可以通过指定一个otypes跳过这一步
In [104]: np.vectorize(np.tan,otypes='O')(arr)
Out[104]:
array([array([[1.55740772, 1.55740772, 1.55740772]]),
array([[1.55740772, 1.55740772, 1.55740772, 1.55740772],
[1.55740772, 1.55740772, 1.55740772, 1.55740772]]),
array([[1.55740772, 1.55740772],
[1.55740772, 1.55740772],
[1.55740772, 1.55740772]])], dtype=object)对象数组迭代在速度上介于列表迭代和数值数组迭代之间。它有一些数组开销,但不是全部。元素是指针,就像在列表中一样。
frompyfunc可以比显式迭代快一点(高达2倍)。vectorize比较慢,因为它有一些开销。这些函数的最大优点是它们可以处理广播。做你自己的计时,看看它们是否有帮助。
https://stackoverflow.com/questions/48853179
复制相似问题