用上限和下限替换列表值的 Pythonic 方法(钳位、裁剪、阈值)?

Pythonic way to replace list values with upper and lower bound (clamping, clipping, thresholding)?

我想替换列表中的大纲。因此我定义了一个上限和下限。现在 upper_bound 以上和 lower_bound 以下的每个值都替换为绑定值。我的方法是使用 numpy 数组分两步完成此操作。

现在我想知道是否可以一步完成,因为我猜它可以提高性能和可读性。

有更短的方法吗?

import numpy as np

lowerBound, upperBound = 3, 7

arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

arr[arr > upperBound] = upperBound
arr[arr < lowerBound] = lowerBound

# [3 3 3 3 4 5 6 7 7 7]
print(arr)

您可以使用 numpy.clip:

In [1]: import numpy as np

In [2]: arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [3]: lowerBound, upperBound = 3, 7

In [4]: np.clip(arr, lowerBound, upperBound, out=arr)
Out[4]: array([3, 3, 3, 3, 4, 5, 6, 7, 7, 7])

In [5]: arr
Out[5]: array([3, 3, 3, 3, 4, 5, 6, 7, 7, 7])

对于不依赖于 numpy 的替代方案,您总是可以这样做

arr = [max(lower_bound, min(x, upper_bound)) for x in arr]

如果你只是想设置一个上限,你当然可以写arr = [min(x, upper_bound) for x in arr]。或者类似地,如果您只想要一个下限,则可以使用 max

在这里,我刚刚应用了两个操作,写在一起。

编辑:这里稍微深入一点的解释:

给定数组的一个元素 x(并假设您的 upper_bound 至少与 lower_bound 一样大!),您将遇到以下三种情况之一:

  1. x < lower_bound
  2. x > upper_bound
  3. lower_bound <= x <= upper_bound.

在情况 1 中,max/min 表达式首先求值为 max(lower_bound, x),然后解析为 lower_bound

在情况 2 中,表达式首先变为 max(lower_bound, upper_bound),然后变为 upper_bound

在情况 3 中,我们得到 max(lower_bound, x) 解析为 x.

在这三种情况下,输出都是我们想要的。