我有一个大的numpy数组mail
,形状不明确,我想构造一个形状相同的数组k
,当d
中的相应条目介于两个常量之间时,它是1.0 k
和lo
,否则为0.0。 (由于较大的代码正在做什么,我不想要一个布尔值数组。)
显而易见的方法是
hi
但是,d = np.ones_like(k)
d[np.less(k, lo)] = 0
d[np.greater(k, hi)] = 0
和np.less
调用涉及创建大型临时布尔数组,我测量这是一个重要的开销。有没有办法执行此操作,不涉及创建任何大的临时对象,同时保持完全矢量化?
答案 0 :(得分:1)
正如其他人所说,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
来编译扩展等。这样做的好处是否值得麻烦取决于你。
答案 1 :(得分:0)
您可以根据比较创建布尔数组,然后转换为浮点类型,一气呵成,就像这样 -
d = ((k >=lo) & (k <= hi)).astype(float)
答案 2 :(得分:0)
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慢。但差异并不大。