Подтвердить что ты не робот

Pythonic способ заменить значения списка верхней и нижней границей (зажим, обрезка, пороговое значение)?

Я хочу заменить outliners из списка. Поэтому я определяю верхнюю и нижнюю границы. Теперь каждое значение выше 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)
4b9b3361

Ответ 1

Вы можете использовать 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])

Ответ 2

Для альтернативы, которая не полагается на 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!), у вас будет один из трех случаев:

i) x < lower_bound

ii) x > upper_bound

iii) lower_bound <= x <= upper_bound.

В случае (i) выражение max/min сначала оценивается как max(lower_bound, x), которое затем переходит в lower_bound.

В случае (ii) выражение сначала становится max(lower_bound, upper_bound), которое затем становится upper_bound.

В случае (iii) получаем max(lower_bound, x), который разрешается только x.

Во всех трех случаях вывод - это то, что мы хотим.