[英]Most efficient way to do (lo <= k && k <= hi) ? 1 : 0 for k a numpy array, lo, hi constants
我有一個大的numpy數組k
,具有未指定的形狀,我想構造一個相同形狀的數組d
,當k
的相應條目在兩個常數lo
和hi
之間時為1.0,否則為0.0。 (因為什么較大的代碼是干什么的,我不想一個布爾值數組)。
顯而易見的方法是
d = np.ones_like(k)
d[np.less(k, lo)] = 0
d[np.greater(k, hi)] = 0
但是, np.less
和np.greater
調用涉及創建大型臨時布爾數組,我測量這是一個重要的開銷。 有沒有辦法執行此操作,不涉及創建任何大型臨時對象,同時保持完全矢量化?
正如有人說,numpy的是在臨時緩沖區沉重,它並沒有提供過它太多的控制。 如果內存占用確實是一個阻塞,你可以放入自己的小程序。 例如,
def process(x, lo, hi):
""" lo <= x < hi ? 1.0 : 0.0."""
x_shape = x.shape
xx = np.ascontiguousarray(x).ravel()
out = np.empty_like(xx)
_process(xx, lo, hi, out)
return out.reshape(x_shape)
_process
在cython中的位置:
%%cython --annotate
import cython
@cython.boundscheck(False)
@cython.wraparound(False)
def _process(double[::1] x, double lo, double hi, double[::1] out):
""" lo <= x < hi ? 1.0 : 0.0."""
cdef:
Py_ssize_t j
double xj
for j in range(x.shape[0]):
xj = x[j]
if lo <= xj < hi:
out[j] = 1.0
else:
out[j] = 0.0
在這里我使用了jupyter筆記本(因此有趣的%%cython
語法)。 在實際項目中,你需要輸入一個setup.py
來編譯擴展等。這樣做的好處是否值得麻煩取決於你。
您可以根據比較創建布爾數組,然后轉換為浮點類型,一次性完成,如下所示 -
d = ((k >=lo) & (k <= hi)).astype(float)
less
和greater
采取out
參數:
out=np.ones_like(k)
np.less(k,80,out=out);
out &= np.greater(k,20);
# np.logical_and(np.greater(k,20),out,out=out);
這可能最終會保存一個中間數組。 雖然我與ufunc印象out
的是,它仍然會創建一個臨時數組,但后來只是把它復制到out
。
在一個小的(10x10)陣列上,這比@ zwol的方法快,但比@Divakar的速度慢。 但差異並不大。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.