只有在空间有限的情况下才值得尝试就地执行此操作。如果是这种情况,可以通过迭代数组的扁平视图来稍微加快代码速度。自从reshape
返回一个新视图如果可能 http://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html,数据本身不会被复制(除非原始数据具有不寻常的结构)。
我不知道有什么更好的方法来实现任意 Python 函数的真正就地应用。
>>> def flat_for(a, f):
... a = a.reshape(-1)
... for i, v in enumerate(a):
... a[i] = f(v)
...
>>> a = numpy.arange(25).reshape(5, 5)
>>> flat_for(a, lambda x: x + 5)
>>> a
array([[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29]])
一些时间安排:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> f = lambda x: x + 5
>>> %timeit flat_for(a, f)
1000 loops, best of 3: 1.86 ms per loop
它的速度大约是嵌套循环版本的两倍:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> def nested_for(a, f):
... for i in range(len(a)):
... for j in range(len(a[0])):
... a[i][j] = f(a[i][j])
...
>>> %timeit nested_for(a, f)
100 loops, best of 3: 3.79 ms per loop
当然,矢量化仍然更快,所以如果您可以制作副本,请使用它:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> g = numpy.vectorize(lambda x: x + 5)
>>> %timeit g(a)
1000 loops, best of 3: 584 us per loop
如果你可以重写dim
使用内置的 ufunc,那么请不要vectorize
:
>>> a = numpy.arange(2500).reshape(50, 50)
>>> %timeit a + 5
100000 loops, best of 3: 4.66 us per loop
numpy
操作是否像+=
正如您所期望的那样,您可以通过就地应用程序免费获得 ufunc 的速度。有时甚至更快!看here https://stackoverflow.com/a/10149508/577088举个例子。
顺便说一句,我对这个问题的原始答案(可以在其编辑历史记录中查看)是荒谬的,并且涉及将索引矢量化为a
。它不仅需要做一些时髦的事情来绕过vectorize
's 类型检测机制 http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html#numpy.vectorize,结果证明它和嵌套循环版本一样慢。聪明就这么多了!