如何在不调用 `np.vectorize` 的情况下强制广播函数

How to force a function to broadcast without invoking `np.vectorize`

我想寻找一种强制广播功能的方法。

在某些情况下,function/method 可能会在以后的实例中被覆盖,以保持功能不变。在这种情况下 if

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 之类的方法强制广播函数,但问题是这是低效的,因为它本质上是 for 循环。 (参见 documentation

我们也可以使用像 np.frompyfunc 这样的工厂方法,它允许我们将 python 函数转换为 numpy 通用函数 ufunc 例如参见 [​​=18=]。这优于 np.vectorize,但仍然比内置 ufunc 方法效率低。

我想知道是否有任何有效的 numpy 方法来处理这个问题,即强制广播函数?

如果有更好的方法来广播任意 Python 函数,numpy.vectorize 会使用它。如果你想让它有效地广播,你真的必须在编写函数时考虑到广播。

在常量函数的特殊情况下,您可以使用 numpy.full:

编写广播常量函数
def f(x):
    return numpy.full(numpy.shape(x), 5)

numba.vectorize 也可以比 numpy.vectorize 更有效地向量化函数,但是您需要 Numba,并且您需要以 Numba 可以高效编译的方式编写您的函数。

对于那些没有通用答案的人来说,最好的答案是 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.sinnp.cos 你会注意到 f(arr)master_f_nocopy(arr) 之间的差异几乎可以忽略不计。