NumPy-将值围绕任意边界

时间:2018-07-22 15:26:36

标签: python numpy

我有一个数组x,其值包含在[a, b](包括a,包括b中)内。现在,我想计算x + y(对于随机y),以使x + y仍包含在[a, b]中,方法是将结果值环绕在左边界或右边界(无论哪个交叉) )。

因为一个例子值得一千个单词:

>>> a, b = -5, 5
>>> x = np.array([-4, -2, 0, 2, 4])
>>> wrap(x, 3)  # Compute x + 3.
[-1, 1, 3, -5, -3]
>>> wrap(x, -3)  # Compute x - 3.
[3, -5, -3, -1, 1]

我想出了以下实现,但并不完全令人满意。

def wrap(x, y):
    if y > 0:
        return (x - a + y) % (b - a) + a
    elif y < 0:
        return (x - b + y) % (a - b) + b
    else:
        return x
  1. 此函数无法正确显示包含/排除边界条件;对于wrap(x, -3),它返回array([ 3, 5, -3, -1, 1]),而5应该是-5。我不确定如何包含此功能。
  2. 此外,显式if子句看起来有些虚假,我想知道是否可以更一般的方式处理(次要问题)。

有人知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

通过“包装”,我认为结果应与x+y mod b-a一致。 (请注意,b-a是这种情况下的“窗口大小”)

请考虑特殊情况a==0。我们有:

def wrap(x, y):
    return (x + y) % b

直截了当,对吧?请注意,Python中的%是按底模的-结果的符号始终与除数的符号相同。因此结果将位于[0..b[中。

在更一般的情况下:

def wrap(x, y):
    return (x + y - a) % (b-a) + a

直接证明返回值与x+y mod b-a是一致的。

还请注意,这是OP代码中的第一种情况。对于y的所有值均有效。


但是,如果x是一个numpy数组,它将执行len(x) %操作,这可能会很慢。因此,可以执行以下操作:

def wrap2(x, y):
    y %= b - a
    x = x + y
    return x - (b-a)*(x >= b)

应该更快。 Try it online!

说明:

  • y %= b-a:将y减小到[0..b-a[范围。这不会影响结果。
  • x = x + y:将y添加到x。在此步骤之后,x将包含正确的值,以b-a为模。 x中的所有值都应在[a..b+(b-a)[范围内。
  • x - (b-a)*(x >= b):如果(x >= b)1(如果解释为整数)则为x >= b,否则为0。从b-a中减去x乘以b-a的所有值,然后减去>= b,并使这些< b保持不变。

答案 1 :(得分:0)

假设您的输入数组已经在[a,b)范围内,那么我们可以将wrap重写为以下函数;

def wrap(x,y,a,b):
    if y > 0:
        x += y
        x[x >=b] -= (b-a)
    elif y < 0:
        x += y
        x[x < a] += (b-a)
    return x