将函数应用于 numpy 数组元素的有效方法?
Efficient way to apply a function to elements of a numpy array?
我有一个巨大的 1D numpy 布尔数组 w
和一个不断增加的索引列表 i
,它将 w
分成 len(i)+1
个子数组。一个玩具示例是:
w=numpy.array([True,False,False,False,True,True,True,True,False,False])
i=numpy.array([0,0,2,5,5,8,8])
我想计算一个 numpy 数组 wi
,如果第 i
个子数组包含 True
,则第 i
个条目为 1,否则为 0。换句话说,w
的第 i
个条目是 w
的第 i
个子数组的元素之和(逻辑 'or')。在我们的示例中,输出为:
[0 0 1 1 0 1 0 0]
这是用代码实现的:
wi=numpy.fromiter(map(numpy.any,numpy.split(w,i)),int)
是否有更有效的方法,或者就内存而言这是最优的?
P.S。 related post
让我们试试np.add.reductat
:
wi = np.add.reduceat(w,np.r_[0,i]).astype(bool)
输出:
array([1, 1, 0, 1, 0, 0])
和表现:
%timeit -n 100 wi = np.add.reduceat(w,np.r_[0,i]).astype(bool).astype(int)
21.7 µs ± 7.86 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit -n 100 wi=np.fromiter(map(np.any,np.split(w,i)),int)
44.5 µs ± 7.79 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
所以我们在这里看到大约 2 倍的速度。
为了提高效率(内存和性能),请使用 np.bitwise_or.reduceat
,因为它将输出保持为布尔值 -
In [10]: np.bitwise_or.reduceat(w,np.r_[0,i])
Out[10]: array([ True, True, False, True, False, False])
要获得 int 输出,请查看 int
-
In [11]: np.bitwise_or.reduceat(w,np.r_[0,i]).view('i1')
Out[11]: array([1, 1, 0, 1, 0, 0], dtype=int8)
这里是all-weather解决方案-
def slice_reduce_or(w, i):
valid = i<len(w)
invalidc =( ~valid).sum()
i = i[valid]
mi = np.r_[i[:-1]!=i[1:],True]
pp = i[mi]
p1 = np.bitwise_or.reduceat(w,pp)
N = len(i)+1
out = np.zeros(N+invalidc, dtype=bool)
out[1:N][mi] = p1
out[0] = w[:i[0]].any()
return out.view('i1')
我有一个巨大的 1D numpy 布尔数组 w
和一个不断增加的索引列表 i
,它将 w
分成 len(i)+1
个子数组。一个玩具示例是:
w=numpy.array([True,False,False,False,True,True,True,True,False,False])
i=numpy.array([0,0,2,5,5,8,8])
我想计算一个 numpy 数组 wi
,如果第 i
个子数组包含 True
,则第 i
个条目为 1,否则为 0。换句话说,w
的第 i
个条目是 w
的第 i
个子数组的元素之和(逻辑 'or')。在我们的示例中,输出为:
[0 0 1 1 0 1 0 0]
这是用代码实现的:
wi=numpy.fromiter(map(numpy.any,numpy.split(w,i)),int)
是否有更有效的方法,或者就内存而言这是最优的?
P.S。 related post
让我们试试np.add.reductat
:
wi = np.add.reduceat(w,np.r_[0,i]).astype(bool)
输出:
array([1, 1, 0, 1, 0, 0])
和表现:
%timeit -n 100 wi = np.add.reduceat(w,np.r_[0,i]).astype(bool).astype(int)
21.7 µs ± 7.86 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit -n 100 wi=np.fromiter(map(np.any,np.split(w,i)),int)
44.5 µs ± 7.79 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
所以我们在这里看到大约 2 倍的速度。
为了提高效率(内存和性能),请使用 np.bitwise_or.reduceat
,因为它将输出保持为布尔值 -
In [10]: np.bitwise_or.reduceat(w,np.r_[0,i])
Out[10]: array([ True, True, False, True, False, False])
要获得 int 输出,请查看 int
-
In [11]: np.bitwise_or.reduceat(w,np.r_[0,i]).view('i1')
Out[11]: array([1, 1, 0, 1, 0, 0], dtype=int8)
这里是all-weather解决方案-
def slice_reduce_or(w, i):
valid = i<len(w)
invalidc =( ~valid).sum()
i = i[valid]
mi = np.r_[i[:-1]!=i[1:],True]
pp = i[mi]
p1 = np.bitwise_or.reduceat(w,pp)
N = len(i)+1
out = np.zeros(N+invalidc, dtype=bool)
out[1:N][mi] = p1
out[0] = w[:i[0]].any()
return out.view('i1')