Clip Values Between a Minimum and Maximum Allowed Value in R

Clip values between a minimum and maximum allowed value in R

Rcpp has clamp for this:

cppFunction('NumericVector rcpp_clip( NumericVector x, double a, double b){
return clamp( a, x, b ) ;
}')

Here is a quick benchmark showing how it performs against other methods discussed :

pmin_pmax_clip <- function(x, a, b) pmax(a, pmin(x, b) )
ifelse_clip <- function(x, a, b) {
ifelse(x <= a, a, ifelse(x >= b, b, x))
}
operations_clip <- function(x, a, b) {
a + (x-a > 0)*(x-a) - (x-b > 0)*(x-b)
}
x <- rnorm( 10000 )
require(microbenchmark)

microbenchmark(
pmin_pmax_clip( x, -2, 2 ),
rcpp_clip( x, -2, 2 ),
ifelse_clip( x, -2, 2 ),
operations_clip( x, -2, 2 )
)
# Unit: microseconds
# expr min lq median uq max
# 1 ifelse_clip(x, -2, 2) 2809.211 3812.7350 3911.461 4481.0790 43244.543
# 2 operations_clip(x, -2, 2) 228.282 248.2500 266.605 1120.8855 40703.937
# 3 pmin_pmax_clip(x, -2, 2) 260.630 284.0985 308.426 336.9280 1353.721
# 4 rcpp_clip(x, -2, 2) 65.413 70.7120 84.568 92.2875 1097.039

Setting min and max values for matrix cells when running a for loop in r

How about a clip function

clip<-function(x, min=0, max=1) {
x[x<min]<-min;
x[x>max]<-max;
x
}

This will set all values < min to the min, and all values > max to max. So if you subtract .9 from every cell, you expect a lot of negatives, but clip will change those to 0's

 clip(M-.9)

same goes for adding .9

 clip(M+.9)

Or was the problem that you were trying to subtract of the min? When doing something like

for (i in 1:50){
M[,]<-M[,]-0.01
}

That statement inside the loop is operating on every element of the vector each time. So you're really subtracting off 0.5. Which is probably too much.

Clip outliers in columns in df2,3,4... based on quantiles from columns in df.tr

So just write a function that directly computes the quantile, then directly applies clipping to each column. The <- conditional assignment inside your lapply call is bogus; you want ifelse to return a vectorized expression for the entire column, already. ifelse is your friend, for vectorization.

# Make up some dummy df2 output (it's supposed to have 1000 cols really)
df2 <- data.frame(d=runif(1000), e=rnorm(1000), f=runif(1000))

require(plyr)
print(colwise(summary)(df2)) # show the summary before we clamp...

# Compute quantiles on df1...
df1 <- df
df1.quantiles <- apply(df1, 2, function(x, prob=0.9) { quantile(x, prob, names=F) })

# ...now clamp by sweeping col-index across both quantile vector, and df2 cols
clamp <- function(x, xmax) { ifelse(x<=xmax, x, xmax) }
for (j in 1:ncol(df2)) {
df2[,j] <- clamp(df2[,j], df1.quantiles[j]) # don't know how to use apply(...,2,)
}

print(colwise(summary)(df2)) # show the summary after we clamp...

Reference:
[1] "Clip values between a minimum and maximum allowed value in R"

Ensuring values in matrix are between a set range?

Something like

m[] <- pmax(0,pmin(10,m))

The m[] on the lefthand side (rather than m) ensures that the matrix keeps its structure.

Here's a (probably unnecessary) example:

lwr <- 0; upr <- 10
set.seed(101)
mRaw <- matrix(runif(100, lwr, upr), nrow=20)
m1 <- sample(c(-1,1),size=100,replace=TRUE)
mAdded <- m1 + mRaw

Now clamp:

mAdded[] <- pmax(lwr,pmin(upr,mAdded))
str(mAdded)
## still a matrix: num [1:20, 1:5] 2.72 0 6.1 7.58 3.5 ...
range(mAdded) ## 0 10

Standard way to clamp a number between two values in Swift

Swift 4/5

Extension of Comparable/Strideable similar to ClosedRange.clamped(to:_) -> ClosedRange from standard Swift library.

extension Comparable {
func clamped(to limits: ClosedRange<Self>) -> Self {
return min(max(self, limits.lowerBound), limits.upperBound)
}
}

#if swift(<5.1)
extension Strideable where Stride: SignedInteger {
func clamped(to limits: CountableClosedRange<Self>) -> Self {
return min(max(self, limits.lowerBound), limits.upperBound)
}
}
#endif

Usage:

15.clamped(to: 0...10) // returns 10
3.0.clamped(to: 0.0...10.0) // returns 3.0
"a".clamped(to: "g"..."y") // returns "g"

// this also works (thanks to Strideable extension)
let range: CountableClosedRange<Int> = 0...10
15.clamped(to: range) // returns 10

How to clamp an integer to some range?

This is pretty clear, actually. Many folks learn it quickly. You can use a comment to help them.

new_index = max(0, min(new_index, len(mylist)-1))

How do I find the maximum element from a list in CLIPS?

You can use the max function to find the maximum value of its arguments. You can bind the list of numbers to a multifield variable in the conditions of a rule. The max function however expects separate arguments so you can't just pass it a multifield value. You can use the expand$ function to split a multifield value into separate arguments for a function call. The max function expects at least 2 arguments in CLIPS 6.3 and at least 1 in CLIPS 6.4, so for completeness you would need to handle these cases. You can create a deffunction to handle these edge cases in your code.

         CLIPS (6.31 6/12/19)
CLIPS>
(deffunction my-max ($?values)
(switch (length$ ?values)
(case 0 then (return))
(case 1 then (return (nth$ 1 ?values)))
(default (return (max (expand$ ?values))))))
CLIPS>
(deffacts list
(list 1 2 3 4 5 6 7 6 5 4 3 2 1))
CLIPS>
(defrule list-max
(list $?values)
=>
(printout t "list max = " (my-max ?values) crlf))
CLIPS>
(deftemplate patient
(slot name)
(slot age)
(multislot tens_max)
(multislot tens_min))
CLIPS>
(deffacts data_patient
(patient (name John) (age 22) (tens_max 13 15 22 11) (tens_min 6 7 14 6)))
CLIPS>
(defrule patient-max
(patient (tens_min $?values))
=>
(printout t "patient max = " (my-max ?values) crlf))
CLIPS> (reset)
CLIPS> (run)
patient max = 14
list max = 7
CLIPS>

Maximum and minimum caps for list values in Python

Use min, max functions:

>>> min(266, 255)
255
>>> max(-15, 0)
0

>>> oldList = [266, 40, -15, 13]
>>> [max(min(x, 255), 0) for x in oldList]
[255, 40, 0, 13]

Taking minimum value of each entry +- 10 rows either side in numpy array

Approach #1

Here's one approach with np.lib.stride_tricks.as_strided -

def strided_3D_axis1(array_3d, L):
s0,s1,s2 = array_3d.strides
strided = np.lib.stride_tricks.as_strided
m,n,r = array_3d.shape
nL = n-L+1
return strided(array_3d, (m,nL,L,r),(s0,s1,s1,s2))

out = strided_3D_axis1(array_3d, L=21).min(axis=-2)

Sample run -

1) Input :

In [179]: array_3d
Out[179]:
array([[[73, 65, 51, 76, 59],
[74, 57, 75, 53, 70],
[60, 74, 52, 54, 60],
[54, 52, 62, 75, 50],
[68, 56, 68, 63, 77]],

[[62, 70, 60, 79, 74],
[70, 68, 50, 74, 57],
[63, 57, 69, 65, 54],
[63, 63, 68, 58, 60],
[70, 66, 65, 78, 78]]])

2) Strided view :

In [180]: strided_3D_axis1(array_3d, L=3)
Out[180]:
array([[[[73, 65, 51, 76, 59],
[74, 57, 75, 53, 70],
[60, 74, 52, 54, 60]],

[[74, 57, 75, 53, 70],
[60, 74, 52, 54, 60],
[54, 52, 62, 75, 50]],

[[60, 74, 52, 54, 60],
[54, 52, 62, 75, 50],
[68, 56, 68, 63, 77]]],

[[[62, 70, 60, 79, 74],
[70, 68, 50, 74, 57],
[63, 57, 69, 65, 54]],

[[70, 68, 50, 74, 57],
[63, 57, 69, 65, 54],
[63, 63, 68, 58, 60]],

[[63, 57, 69, 65, 54],
[63, 63, 68, 58, 60],
[70, 66, 65, 78, 78]]]])

3) Strided view based min :

In [181]: strided_3D_axis1(array_3d, L=3).min(axis=-2)
Out[181]:
array([[[60, 57, 51, 53, 59],
[54, 52, 52, 53, 50],
[54, 52, 52, 54, 50]],

[[62, 57, 50, 65, 54],
[63, 57, 50, 58, 54],
[63, 57, 65, 58, 54]]])

Approach #2

Here's another with broadcasting upon creating all sliding indices along the second axis -

array_3d[:,np.arange(array_3d.shape[1]-L+1)[:,None] + range(L)].min(-2)

Approach #3

Here's another using Scipy's 1D minimum filter -

from scipy.ndimage.filters import minimum_filter1d as minf

L = 21
hL = (L-1)//2
out = minf(array_3d,L,axis=1)[:,hL:-hL]

Runtime test -

In [231]: array_3d = np.random.randint(50, 80, (3, 50, 18))

In [232]: %timeit strided_3D_axis1(array_3d, L=21).min(axis=-2)
10000 loops, best of 3: 54.2 µs per loop

In [233]: %timeit array_3d[:,np.arange(array_3d.shape[1]-L+1)[:,None] + range(L)].min(-2)
10000 loops, best of 3: 81.3 µs per loop

In [234]: L = 21
...: hL = (L-1)//2
...:

In [235]: %timeit minf(array_3d,L,axis=1)[:,hL:-hL]
10000 loops, best of 3: 32 µs per loop

R ggplot2 - How do I specify out of bounds values' colour

As you said youself, you want the oob argument in the scale_fill_gradient. To clamp values, you can use squish from the scales package (scales is installed when ggplot2 is installed):

library(scales)

and later

scale_fill_gradient(low = "red", high = "green", limits=c(0.6, 1), oob=squish)


Related Topics



Leave a reply



Submit