将 numpy 舍入到最近的步骤

发布于 2024-12-11 08:26:31 字数 632 浏览 2 评论 0原文

我想知道如何将 numpy 中的数字舍入到上限或下限阈值,该阈值是预定义步长的函数。希望以更清晰的方式说明,如果我有数字 123 且步长等于 50,我需要将 123 舍入到最接近的 150 或 100,在本例中为 100。我得出了下面的函数,它可以完成这项工作但我想知道是否有更好、更简洁的方法来做到这一点。

预先感谢,

保罗

def getRoundedThresholdv1(a, MinClip):
    import numpy as np
    import math
    digits = int(math.log10(MinClip))+1
    b = np.round(a, -digits)
    if b > a:  # rounded-up
        c = b - MinClip
        UpLow = np.array((b,c))
    else:  # rounded-down
        c = b + MinClip
        UpLow = np.array((c,b))
    AbsDelta = np.abs(a - UpLow)
    return UpLow[AbsDelta.argmin()]




getRoundedThresholdv1(143, 50)

I would like to know how I can round a number in numpy to an upper or lower threshold which is function of predefined step size. Hopefully stated in a clearer way, if I have the number 123 and a step size equal to 50, I need to round 123 to the closest of either 150 or 100, in this case 100. I came out with function below which does the work but I wonder if there is a better, more succint, way to do this.

Thanks in advance,

Paolo

def getRoundedThresholdv1(a, MinClip):
    import numpy as np
    import math
    digits = int(math.log10(MinClip))+1
    b = np.round(a, -digits)
    if b > a:  # rounded-up
        c = b - MinClip
        UpLow = np.array((b,c))
    else:  # rounded-down
        c = b + MinClip
        UpLow = np.array((c,b))
    AbsDelta = np.abs(a - UpLow)
    return UpLow[AbsDelta.argmin()]




getRoundedThresholdv1(143, 50)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十二 2024-12-18 08:26:31

pb360 的解决方案要好得多,使用 python3 中内置 round 的第二个参数。

我认为你不需要numpy

def getRoundedThresholdv1(a, MinClip):
    return round(float(a) / MinClip) * MinClip

这里a是一个数字,如果你想向量化这个函数你只需要替换roundnp.roundfloat(a)np.array(a, dtype=float)

The solution by pb360 is much better, using the second argument of builtin round in python3.

I think you don't need numpy:

def getRoundedThresholdv1(a, MinClip):
    return round(float(a) / MinClip) * MinClip

here a is a single number, if you want to vectorize this function you only need to replace round with np.round and float(a) with np.array(a, dtype=float)

小巷里的女流氓 2024-12-18 08:26:31

摘要:这是一种正确的方法,最佳答案有不起作用的情况:

def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float:
    """Rounds a given quantity to a specific step size
    :param quantity: required
    :param step_size: required
    :return: decimal
    """
    precision: int = int(round(-math.log(step_size, 10), 0))
    return float(round(quantity, precision))

我的声誉太低,无法对 Ruggero Turra 的最佳答案发表评论并指出问题。然而,它也有不起作用的情况,例如:

def getRoundedThresholdv1(a, MinClip):
    return round(float(a) / MinClip) * MinClip

getRoundedThresholdv1(quantity=13.200000000000001, step_size=0.0001)

无论使用 numpy 还是标准库回合,都会立即返回 13.200000000000001 。我什至通过对该功能进行压力测试都没有发现这一点。它只是在生产代码中使用它时出现并抛出错误。

请注意,此答案的全部功劳来自开源 github 存储库,该存储库不是我发现的 这里

Summary: This is a correct way to do it, the top answer has cases that do not work:

def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float:
    """Rounds a given quantity to a specific step size
    :param quantity: required
    :param step_size: required
    :return: decimal
    """
    precision: int = int(round(-math.log(step_size, 10), 0))
    return float(round(quantity, precision))

My reputation is too low to post a comment on the top answer from Ruggero Turra and point out the issue. However it has cases which did not work for example:

def getRoundedThresholdv1(a, MinClip):
    return round(float(a) / MinClip) * MinClip

getRoundedThresholdv1(quantity=13.200000000000001, step_size=0.0001)

Returns 13.200000000000001 right back whether using numpy or the standard library round. I didn't even find this by stress testing the function. It just came up when using it in production code and spat an error.

Note full credit for this answer comes out of an open source github repo which is not mine found here

你爱我像她 2024-12-18 08:26:31

请注意,在 Ruggero Turra 中,round() 的答案会四舍五入到最接近的偶数。含义:

a= 0.5
round(a)

Out: 0

这可能不是你所期望的。

如果您想要“经典”舍入,可以使用此函数,它支持标量和 Numpy 数组:

import Numpy as np

def getRoundedThresholdv1(a, MinClip):
    scaled = a/MinClip
    return np.where(scaled % 1 >= 0.5, np.ceil(scaled), np.floor(scaled))*MinClip

或者,您可以使用 Numpy 的方法 digitize。它要求您定义步骤数组。 数字化会将您的价值ceil到下一步。因此,为了以“经典”方式进行舍入,我们需要一个中间步骤。

您可以使用它:

import Numpy as np
    
def getRoundedThresholdv1(a, MinClipBins):
    intermediate = (MinClipBins[1:] + MinClipBins[:-1])/2
    return MinClipBins[np.digitize(a, intermediate)]

然后您可以像这样调用它:

bins = np.array([0,  50, 100, 150])
test1 = getRoundedThresholdv1(74, bins)
test2 = getRoundedThresholdv1(125, bins)

这给出:

test1 = 50
test2 = 150 

Note that round() in Ruggero Turra his answer rounds to the nearest even integer. Meaning:

a= 0.5
round(a)

Out: 0

Which may not be what you expect.

In case you want 'classical' rounding, you can use this function, which supports both scalars and Numpy arrays:

import Numpy as np

def getRoundedThresholdv1(a, MinClip):
    scaled = a/MinClip
    return np.where(scaled % 1 >= 0.5, np.ceil(scaled), np.floor(scaled))*MinClip

Alternatively, you could use Numpy's method digitize. It requires you to define the array of your steps. digitize will kind of ceil your value to the next step. So in order to round in a 'classical' way we need an intermediate step.

You can use this:

import Numpy as np
    
def getRoundedThresholdv1(a, MinClipBins):
    intermediate = (MinClipBins[1:] + MinClipBins[:-1])/2
    return MinClipBins[np.digitize(a, intermediate)]

You can then call it like:

bins = np.array([0,  50, 100, 150])
test1 = getRoundedThresholdv1(74, bins)
test2 = getRoundedThresholdv1(125, bins)

Which gives:

test1 = 50
test2 = 150 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文