最有效的方法(lo< = k&& k< = hi)? 1:0表示k a numpy数组,lo,hi常数

时间:2016-05-11 17:06:15

标签: python performance python-3.x numpy

我有一个大的numpy数组mail,形状不明确,我想构造一个形状相同的数组k,当d中的相应条目介于两个常量之间时,它是1.0 klo,否则为0.0。 (由于较大的代码正在做什么,我想要一个布尔值数组。)

显而易见的方法是

hi

但是,d = np.ones_like(k) d[np.less(k, lo)] = 0 d[np.greater(k, hi)] = 0 np.less调用涉及创建大型临时布尔数组,我测量这是一个重要的开销。有没有办法执行此操作,不涉及创建任何大的临时对象,同时保持完全矢量化?

3 个答案:

答案 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)

lessgreater采用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慢。但差异并不大。