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
Combine Multiple Plots, Generated Using the "By" R Function, in One Figure
Referring to Variables by Name in a Dplyr Function Returns Object Not Found Error
How to Organize Large Shiny Apps
Dplyr Summarise_Each with Na.Rm
Figures Captions and Labels in Knitr
Piecewise Regression with R: Plotting the Segments
Formatting Ggplot2 Axis Labels with Commas (And K? Mm) If I Already Have a Y-Scale
Get Selected Row from Datatable in Shiny App
R: Unexpected Results from P.Adjust (Fdr)
How to Increase Size of the Points in Ggplot2, Similar to Cex in Base Plots
Obtaining Separate Summary Statistics by Categorical Variable with Stargazer Package
Ggplot2: How to Remove Slash from Geom_Density Legend
Avoid That Space in Column Name Is Replaced with Period (".") When Using Read.Csv()