Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a more elegant way to project x between 0 and 1 to a w-shape?

Tags:

r

projection

I need to project values (x) between 0 and 1 to a w shape (y=f(x)):

enter image description here

I can achieve what I need with the following function:

f <- function(x) {
  if (x < 0.25) {
    return (1-4*x)
  }
  if (x < 0.50) {
    return (-1 + 4*x)
  }
  if (x < 0.75) {
    return (3 - 4*x)
  }
  return (-3 + 4*x)
}


x <- 0:20/20
y <- lapply(x, f)

plot(x, y)
lines(x,y, col='red')

However, I am inclined to believe that there is a more elegant solution, possibly a one liner, to my problem.

Is there such a thing in R?

like image 509
René Nyffenegger Avatar asked Dec 19 '25 00:12

René Nyffenegger


2 Answers

f <- function(x)
abs(abs(2 - 4 * x) - 1)

plot(f)

enter image description here

like image 160
Hong Ooi Avatar answered Dec 20 '25 15:12

Hong Ooi


Here is a vectorised solution.

f2 <- function(x) {
  y <- 1 - 4 * x
  y[0.25 <= x  & x < 0.50] <- -1 + 4 * x[0.25 <= x  & x < 0.50]
  y[0.50 <= x  & x < 0.75] <-  3 - 4 * x[0.50 <= x  & x < 0.75]
  y[0.75 <= x]             <- -3 + 4 * x[0.75 <= x]
  return(y)
}

This has the benefit that it is much faster

x <- seq(0, 1, length = 1001)
library(microbenchmark)
microbenchmark(
  original = {y1 <- sapply(x, f)},
  vectorised = {y2 <- f2(x)}
)
all.equal(y1, y2)

The timings

Unit: microseconds
       expr      min        lq       mean    median       uq      max neval cld
   original 1170.487 1198.0590 1500.39726 1534.2840 1566.953 8317.288   100   b
 vectorised   51.767   55.2405   58.65856   56.9055   58.981  107.117   100  a 
like image 41
Thierry Avatar answered Dec 20 '25 15:12

Thierry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!