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

2024-04-26 21:03:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个大的numpy数组k,形状未明,我想构造一个形状相同的数组d,当k中对应的条目在两个常量lohi之间时,它是1.0,否则为0.0。(由于较大的代码正在执行的操作,我不希望使用布尔值数组。)

最明显的方法是

d = np.ones_like(k)
d[np.less(k, lo)] = 0
d[np.greater(k, hi)] = 0

然而,np.lessnp.greater调用涉及到创建大型scratch布尔数组,我已经测量到这是一个很大的开销。有没有一种方法可以在保持完全矢量化的情况下执行此操作,而不需要创建任何大的scratch对象?你知道吗


Tags: 方法代码numpylonpones条目数组
3条回答

您可以基于比较创建布尔数组,然后一次性转换为浮点类型,如下所示-

d = ((k >=lo) & (k <= hi)).astype(float)

正如其他人所说,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来编译扩展等,这样做的好处是否值得麻烦取决于您自己。你知道吗

lessgreaterout参数:

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的方法慢,但差别不大。你知道吗

相关问题 更多 >