4

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))

2
  • 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. Commented 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.
    – Emily
    Commented May 24, 2016 at 19:01

1 Answer 1

13

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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.