The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
Learn how to clamp numeric values to limits, test whether values fall within an inclusive range, and wrap angles or other periodic measurements in R with the dependency-free numops package.
The bounds functions are related, but they answer different questions.
| Goal | Function | Interval |
|---|---|---|
| Replace values outside fixed limits | clamp() |
[lower, upper] |
| Restrict probabilities or proportions | clamp01() |
[0, 1] |
| Identify values inside fixed limits | in_range() |
[lower, upper] |
| Map periodic values to one cycle | wrap() |
[lower, upper) |
clamp() and clamp01() modify values.
in_range() returns logical results without changing its
input. wrap() uses modular arithmetic rather than replacing
values at the nearest boundary.
clamp() restricts each value to the closed interval
[lower, upper]. Its element-wise formula is
min(max(x, lower), upper)
Values inside the interval remain unchanged. Values below or above it are replaced by the nearest boundary.
The equivalent base R expression requires nested parallel extrema.
Both boundaries are included, so values equal to lower
or upper remain unchanged.
clamp01() is equivalent to clamp(x, 0, 1).
It is convenient when small numerical errors produce probabilities or
proportions just outside their valid interval.
Clamping changes invalid values, while range testing only identifies them.
in_range(probabilities, lower = 0, upper = 1)
#> [1] FALSE TRUE TRUE FALSE
clamp01(probabilities)
#> [1] 0.00 0.25 0.80 1.00When unexpected values may indicate a data problem, test and investigate them before deciding whether clamping is appropriate.
in_range() evaluates the inclusive condition
x >= lower & x <= upper
The logical result can be used directly for filtering.
Both endpoints belong to the interval.
Missing inputs produce missing logical results rather than
TRUE or FALSE.
wrap() maps values to the half-open interval
[lower, upper). Its conceptual formula is
lower + (x - lower) %% (upper - lower)
The implementation uses an equivalent calculation that avoids unnecessary overflow.
Angles outside a canonical rotation can be wrapped to
[0, 360).
angles <- c(-370, -10, 0, 360, 370, 725)
wrap(angles, lower = 0, upper = 360)
#> [1] 350 350 0 0 10 5The lower boundary is included and the upper boundary is excluded. Therefore, an angle of 360 degrees maps to zero rather than remaining 360.
This differs from in_range(), which always includes both
boundaries. To test whether an angle is already in the canonical
half-open interval, use an explicit upper comparison.
The same operation applies to clock times.
A symmetric interval is often useful for phase angles.
Wrapping produces a repeating sawtooth pattern. Each complete cycle returns the result to the lower boundary.
angle_sequence <- seq(-720, 720, length.out = 500)
plot(
angle_sequence,
wrap(angle_sequence, lower = 0, upper = 360),
type = "l",
xlab = "Original angle",
ylab = "Wrapped angle",
main = "Wrapping angles to [0, 360)"
)Bounds may have length one or the same length as the values being processed. Scalar bounds are recycled to the shared length.
Vectorized bounds allow each position to use a different interval.
x <- c(-2, 5, 20)
lower <- c(0, 0, 10)
upper <- c(1, 10, 15)
clamp(x, lower, upper)
#> [1] 0 5 15
in_range(x, lower, upper)
#> [1] FALSE TRUE FALSEEvery argument must have length one or a shared length. Other combinations are errors rather than partial recycling. Names, dimensions, and dimnames come from the first input already having the shared length.
The bounds functions use consistent rules for missing and non-finite values.
| Condition | Behavior |
|---|---|
Missing value in x |
Produces a missing result |
| Missing bound | Produces an error |
lower > upper |
Produces an error |
Infinite bound in clamp() or
in_range() |
Allowed |
Infinite bound in wrap() |
Produces an error |
Infinite value passed to wrap() |
Produces NaN |
Equal lower and upper bounds in wrap() |
Produces an error |
An empty numeric input is returned with length zero, provided its bounds are valid.
Consider measurements containing probabilities and angles. First record which probabilities are valid before applying any correction.
measurements <- data.frame(
probability = c(-0.02, 0.35, 1.04, NA),
angle = c(-10, 45, 360, 725)
)
measurements$probability_valid <- in_range(
measurements$probability,
lower = 0,
upper = 1
)
measurements
#> probability angle probability_valid
#> 1 -0.02 -10 FALSE
#> 2 0.35 45 TRUE
#> 3 1.04 360 FALSE
#> 4 NA 725 NAIf the out-of-range probabilities are known numerical artifacts, clamp them to the valid interval. Wrap the angles to a canonical rotation at the same time.
measurements$probability <- clamp01(
measurements$probability
)
measurements$angle <- wrap(
measurements$angle,
lower = 0,
upper = 360
)
measurements
#> probability angle probability_valid
#> 1 0.00 350 FALSE
#> 2 0.35 45 TRUE
#> 3 1.00 0 FALSE
#> 4 NA 5 NAThe validation column preserves which probabilities required attention, while the transformed columns are ready for downstream calculations.
The most important distinction among these functions is whether the upper boundary is included.
clamp(): [lower, upper]
in_range(): [lower, upper]
wrap(): [lower, upper)
Use clamp() to enforce limits, in_range()
to validate or filter values, and wrap() to represent
periodic values in a single cycle. Use clamp01() when the
required limits are specifically zero and one.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.