# Rescale raster in R

What's the best way to rescale a raster with range 0, 200 to range -1 to 1 in R? I'm currently using `gdal_translate`, but this requires that I write out a new file with the updated range. If possible I'd like to simply store the new rescaled raster as a variable in R.

`gdal_translate(src_dataset = "input_data_path", dst_dataset = "output_data_path", scale = c(0, 200, -1.0, 1.0))`

• Are you sure that you are after a two-tailed result? Numerically, this is what you will end up with, zero being the inflection point. If the data transformation is intended to be applied to a normal-like distribution, then this makes no sense. These type of distributions (bounding negative and positive) are intended to represent processes that a functionally different as the increase/decrease in the tails. An example is the Moran's-I where -1 and 1 represent significant, but different types, of autocorrelation and zero is random. May 24, 2016 at 18:59
• Yes, the original dataset (0 to 200) is scaled this way because it was stored in a 8-bit structure. The final dataset is an index that ranges from -1 to 1. May 24, 2016 at 19:01

If the original data was rescaled to 8-bit it should be 0-255 and not 0-200. That aside you can take a normalization approach but shift the centrality over so the distribution will bound into the negative. Two normalization formulas that will do this are:

Formula 1: `[(x - "x min") / ("x max" - "x min") - 0.5) * 2]`

Formula 2: `["new min" + (x - "x min") * (("new max" - "new min") / ("x max" - "x min"))]`

In R parlance these are easy formulas to translate to code. Here we create a random vector ranging 0-200 and plot the distribution.

``````x <- round(runif(100,0,200),0)
plot(density(x), xlim=c(0,200))
``````

We then normalize the data, using the first formula, so it ranges -1 to 1 and check to make sure that the distribution did not change shape.

``````x.scale <- ((x - min(x)) / (max(x) - min(x)) - 0.5 ) * 2
plot(density(x.scale), xlim=c(-1,1))
``````

To apply this to a raster we can use exactly the same logic and syntax. To pull the min and max raster values we use `cellStats`.

``````library(raster)
r <- raster(nrows=100, ncols=100)
r[] <- round(runif(ncell(r), 0, 200),0)
r.min = cellStats(r, "min")
r.max = cellStats(r, "max")

r.scale <- ((r - r.min) / (r.max - r.min) - 0.5 ) * 2
r.scale
plot(r.scale)
``````

Here is the second formula put into a rescale function that would work, given the correct arguments, if passed to `calc`. It should work with a single value or a vector distribution. The examples illustrate normalizing single values into the expected distribution based on the definition of current and defined min and max values.

``````rescale <- function(x, x.min = NULL, x.max = NULL, new.min = 0, new.max = 1) {
if(is.null(x.min)) x.min = min(x)
if(is.null(x.max)) x.max = max(x)
new.min + (x - x.min) * ((new.max - new.min) / (x.max - x.min))
}

rescale(200, x.min = 0, x.max = 200, new.min = -1, new.max = 1)
rescale(100, x.min = 0, x.max = 200, new.min = -1, new.max = 1)
rescale(0, x.min = 0, x.max = 200, new.min = -1, new.max = 1)
``````