是否有基于abs值的ceil()函数,如trunc vs floor或roundawayfromzero函数?

2024-06-07 17:45:21 发布

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

numpy.trunc是基于abs值的楼层函数:

a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0])
np.floor(a)
Out[122]: array([-2., -2., -1.,  0.,  1.,  1.,  2.])
np.trunc(a)
Out[123]: array([-1., -1., -0.,  0.,  1.,  1.,  2.])

ceil输出如下:

^{pr2}$

但我需要一个输出:数组([-2.,-2.,-1.,1.,2.,2.,2.]) 这个的numpy函数是什么?在

编辑: 不幸的是,在远离零的函数中没有内置函数。基于@Mitch和@Divakar的答案,我做了一些测试,试图优化速度和内存使用。在

def rawzero1(a): #@Mitch
    return np.sign(a)*np.ceil(np.abs(a))


def rawzero2(a): #@Divakar
    return np.where(a<0, np.floor(a), np.ceil(a))


def rawzero3(a):
    _a = np.abs(a)
    np.ceil(_a, _a) # inplace
    np.copysign(_a, a, out = _a)
    return _a


def rawzero4(a):
    _a = np.ceil(np.abs(a))
    np.copysign(_a, a, out = _a)
    return _a

array size: 762.94 MB

| func     |   t per call (ms) |   max mem use (MB) |   mem to array size (MB) |
|:---------|------------------:|-------------------:|-------------------------:|
| rawzero1 |           1071.34 |            3082.51 |                     4.04 |
| rawzero2 |           1237.74 |            3183.39 |                     4.17 |
| rawzero3 |            543.71 |            1576.41 |                     2.07 |
| rawzero4 |            583.83 |            2328.77 |                     3.05 |

所以最好的是rawzero3,它使用就地操作来减少内存使用量,并使用复制签名来加快速度。在

根据@Divakar更新,需要numexpr>;=2.6.4。在此之前的任何版本都没有ceil()。在

rawzero1(a) == rawzero2(a)
rawzero1(a) == rawzero3(a)
rawzero1(a) == rawzero4(a)
rawzero1(a) == numexpr_1(a)
array size: 762.94 MB
| func      |   t per call (ms) |   max mem use (MB) |   mem to array size (MB) |
|:----------|------------------:|-------------------:|-------------------------:|
| rawzero1  |           1108.68 |            3828.35 |                     5.02 |
| rawzero2  |           1226.78 |            3940.69 |                     5.17 |
| rawzero3  |            531.54 |            2323.55 |                     3.05 |
| rawzero4  |            579.55 |            3082.49 |                     4.04 |
| numexpr_1 |            228.00 |            2323.57 |                     3.05 |

一点也不奇怪。numexpr版本将提供最佳的速度和与rawzero3相同的内存占用。奇怪的是rawzero3的内存占用有点不稳定。理论上它应该只使用2倍的数组大小,而不是3倍


Tags: 函数内存sizereturndefnpmbabs
3条回答

您可以使用此语法 [ np.ceil(x) if x>0 else np.floor(x) for x in lst) ]

手动操作。对功能不确定。在

就像这篇文章One-line list comprehension: if-else variants

方法1:使用np.where根据积极性/消极性在floor和{}之间进行选择-

np.where(a<0, np.floor(a), np.ceil(a))

样本运行-

^{pr2}$

方法2:我们可以扩展^{}中使用的符号技巧,方法是使用与零的比较和缩放来获得sign等价的符号,并利用^{} moduleabs值执行ceil。现在,我们应该记住,numexpr在处理大型数据集时性能更好。因此,实施将是-

import numexpr as ne

ne.evaluate('(2*(a>0)-1)*ceil(abs(a))')

运行时测试

所有方法-

def rawzero1(a):
    return np.sign(a)*np.ceil(np.abs(a))

def rawzero2(a):
    return np.where(a<0, np.floor(a), np.ceil(a))

def rawzero3(a):
    _a = np.abs(a)
    np.ceil(_a, _a) # inplace
    np.copysign(_a, a, out = _a)
    return _a

def rawzero4(a):
    _a = np.ceil(np.abs(a))
    np.copysign(_a, a, out = _a)
    return _a

def numexpr_1(a):
    return ne.evaluate('(2*(a>0)-1)*ceil(abs(a))')

时间安排-

In [52]: a = np.random.randn(1000000)

In [53]: %timeit rawzero1(a)
    ...: %timeit rawzero2(a)
    ...: %timeit rawzero3(a)
    ...: %timeit rawzero4(a)
    ...: %timeit numexpr_1(a)
    ...: 
100 loops, best of 3: 11.6 ms per loop
100 loops, best of 3: 13.2 ms per loop
100 loops, best of 3: 4.9 ms per loop
100 loops, best of 3: 6.54 ms per loop
1000 loops, best of 3: 1.65 ms per loop

In [54]: np.allclose(numexpr_1(a), rawzero1(a))
Out[54]: True

另一个选择(虽然不是内置的)可以取绝对值的上限。在

np.sign(a) * np.ceil(np.abs(a))

相关问题 更多 >

    热门问题