更快速地使用`map`功能

时间:2017-02-21 00:31:59

标签: python arrays python-3.x numpy dictionary

我有一个函数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)))

然而,当函数复杂时(在我的情况下它涉及一些积分),这最后一行非常耗时。有没有办法更快地做到这一点?我很高兴有一个不优雅的解决方案 - 重点是速度。

4 个答案:

答案 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对象,因此需要astypenp.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])