我有一个函数f
,用于exapmle:
def f(x):
return x**2
并希望获得一个由间隔评估的f
组成的数组,例如单位间隔(0,1)。我们可以这样做:
import numpy as np
X = np.arange(0,1,0.01)
arr = np.array(list(map(f, X)))
然而,当函数复杂时(在我的情况下它涉及一些积分),这最后一行非常耗时。有没有办法更快地做到这一点?我很高兴有一个不优雅的解决方案 - 重点是速度。
答案 0 :(得分:2)
您可以使用列表推导来略微减少运行时间。
arr = [f(x) for x in range(0, 5)] # range is the interval
这应该有效。它只会略微减少运行时间。除非您使用map()
的非常大的数字,否则不应该担心运行时。
答案 1 :(得分:1)
使用对整个阵列进行操作的操作。例如,使用一个只对输入求平方的函数(稍微从您的示例中纠正):
def f(x):
return x**2
然后你就做了
arr = f(X)
因为NumPy定义了像**
这样的运算符来同时对整个数组进行操作。
你的真实功能可能不那么简单。你说有涉及的积分;要使整个数组操作与之一起工作,您可能必须以不同方式传递参数或更改用于计算积分的内容。但是,一般来说,整个数组操作将远远超过需要在循环中调用Python级代码的任何内容。
答案 2 :(得分:1)
如果f
如此复杂以至于无法用编译的数组运算来表达,并且只能采用标量,我发现frompyfunc
提供了最佳性能(约为2倍)一个明确的循环)
In [76]: def f(x):
...: return x**2
...:
In [77]: foo = np.frompyfunc(f,1,1)
In [78]: foo(np.arange(4))
Out[78]: array([0, 1, 4, 9], dtype=object)
In [79]: foo(np.arange(4)).astype(int)
Out[79]: array([0, 1, 4, 9])
它返回dtype对象,因此需要astype
。 np.vectorize
也使用它,但速度稍慢。两者都推广到各种形状的输入数组。
对于1d结果fromiter
适用于map
(不包含list
)部分:
In [84]: np.fromiter((f(x) for x in range(4)),int)
Out[84]: array([0, 1, 4, 9])
In [86]: np.fromiter(map(f, range(4)),int)
Out[86]: array([0, 1, 4, 9])
你必须在现实的情况下做自己的时间。
答案 3 :(得分:1)
您可以尝试numpy.vectorize
。这是将函数应用于列表或数组
import numpy as np
def foo(x):
return x**2
foo = np.vectorize(foo)
arr = np.arange(10)
In [1]: foo(arr)
Out[1]: array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81])