Search code examples
pythonarraysnumpyclipclamp

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


I want to replace outliners from a list. Therefore I define a upper and lower bound. Now every value above upper_bound and under lower_bound is replaced with the bound value. My approach was to do this in two steps using a numpy array.

Now I wonder if it's possible to do this in one step, as I guess it could improve performance and readability.

Is there a shorter way to do this?

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)

See How can I clamp (clip, restrict) a number to some range? for clamping individual values, including non-Numpy approaches.


Solution

  • You can use 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])