我想寻找一种强制广播功能的方法。
在某些情况下,以后可能会将函数/方法覆盖为常数函数。在这种情况下,如果
arr = np.arange(0, 1, 0.0001)
f = lambda x: 5
f(arr) # this gives just integer 5, i want [5, 5,..., 5]
我知道像np.vectorize
这样的方法会强制广播函数,但是问题是效率低下,因为它本质上是在幕后循环。 (请参阅documentation)
我们还可以使用诸如np.frompyfunc
之类的工厂方法,该方法允许我们将python函数转换为numpy通用函数ufunc
,例如参见here。这种方法的性能优于np.vectorize
,但仍然比内置ufunc
的方法效率低。
我想知道是否有任何有效的numpy方法来处理此问题,即强制该函数广播?
答案 0 :(得分:1)
如果有更好的方法来广播任意Python函数,则numpy.vectorize
将使用它。如果要有效地广播,您确实必须在编写广播功能时就考虑到这一点。
在常量函数的特定情况下,您可以使用numpy.full
编写广播常量函数:
def f(x):
return numpy.full(numpy.shape(x), 5)
numba.vectorize
还可以比numpy.vectorize
更有效地向量化函数,但是您需要Numba,并且需要以Numba可以有效编译的方式编写函数。
答案 1 :(得分:0)
对于那些无法获得通用答案的人来说,最好的答案是np.full_like(arr, val)
,它比np.full(arr.shape, val)
改善约20%
在将此issue提交给作者之后,我发现了一些最佳的中间立场,可以兼顾一般性和良好表现:
np.broadcast_arrays(x, f(x))[1]
这是一些时间分析:
arr = np.arange(1, 2, 0.0001).reshape(10, -1)
def master_f(x): return np.broadcast_arrays(x, f(x))[-1].copy('K')
def master_f_nocopy(x): return np.broadcast_arrays(x, f(x))[-1]
def vector_f(x): return np.vectorize(f)(x)
%timeit arr+1 # this takes about 10microsec
%timeit master_f(arr) # this takes about 40 mircrosec
%timeit master_f_nocopy(arr) # this takes about 20 microsec
请注意,这允许将其应用于诸如f(x,y):=y
之类的投影功能,这超出了np.full_like
的帮助。
此外,当出现诸如np.sin
和np.cos
之类的更复杂的功能时,您会注意到f(arr)
和master_f_nocopy(arr)
之间的区别几乎可以忽略不计。