5

I am trying to make a function that rescales a vector to lie between two argument lower and upper. And rescaling is done by linear transformation.

# rescales x to lie between lower and upper
rescale <- function(x, lower = 0, upper = 1){
slope <- (upper-lower)/(which.max(x)-which.min(x))
intercept <- slope*(x-which.max(x))+upper
y <- intercept + slope * x
return(list(new = y, coef = c(intercept = intercept, slope = slope)))
}

I have a feeling that I am not on the right track. Please give me some advice to make it right.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
user3358649
  • 51
  • 2
  • 3
  • 1
    This is very close to the indicated duplicate, but allowing arbitrary lower and upper bounds needs a little extra. Hence, I asked for the question do be undeleted but have voted to close it (which is fine, having two related questions *that are linked* is beneficial). – Gavin Simpson Feb 27 '14 at 15:52
  • 1
    The `rescale` function in the `scales` package can do this, and can even handle the case where the range you are scaling from is not identical to the range of the data being scaled. – Brian Diggs Feb 27 '14 at 16:43
  • @BrianDiggs Fancy adding an example as an answer? With the indicated duplicate and this Q we have two good solutions to this problem with a range of answers. – Gavin Simpson Feb 27 '14 at 16:49

1 Answers1

2

Here's a function based on the logic in this related Q&A:

rescale <- function(x, from, to) {
  maxx <- max(x)
  minx <- min(x)
  out <- (to - from) * (x - minx)
  out <- out / (maxx - minx)
  out + from
}

> rescale(1:10, 2, 5)
 [1] 2.000000 2.333333 2.666667 3.000000 3.333333 3.666667 4.000000 4.333333
 [9] 4.666667 5.000000

Note that this won't work if min(x) == max(x) as we'd then be dividing by 0 in the next to last line of the function.

Community
  • 1
  • 1
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453