Changing the scale of a variable to 0-100

  • I have constructed a social capital index using PCA technique. This index comprises values both positive and negative. I want to transform / convert this index to 0-100 scale to make it easy to interpret. Please suggest me an easiest way to do so.

    The logistic function used in logit models might come in handy as well. Depends on specific purpose.

    Scaling existing data to 0-100 has hidden risks when it will be applied to future (or additional) data. See http://www.consumerreports.org/cro/cars/tesla-model-s-p85d-earns-top-road-test-score, for instance, where Consumer Reports wrote "...we faced a quandary: The Tesla initially scored 103 in the Consumer Reports' Ratings system, which by definition doesn’t go past 100. The car set a new benchmark, so we had to make changes to our scoring to account for it."

  • Any variable (univariate distribution) $v$ with observed $min_{old}$ and $max_{old}$ values (or these could be preset potential bounds for values) can be rescaled to range $min_{new}$ to $max_{new}$ by the following formula:

    $\frac{max_{new}-min_{new}}{max_{old}-min_{old}}\cdot (v-max_{old})+max_{new}$

    or

    $\frac{max_{new}-min_{new}}{max_{old}-min_{old}}\cdot (v-min_{old})+min_{new}$.

  • For R there is also already available rescale function from scales package, which does exactly what you want and what @AndrewTulloch and @ttnphns described:

    library(scales)
    rescale(c(-10, -9, -5, 2, 6), to = c(0, 100)) ## Use scales:::rescale() if you have several packages loaded using the same function name
    [1]   0.00   6.25  31.25  75.00 100.00
    
  • first, lets get some example data:

    x <- runif(20, -10, 10)
    

    Here are two functions that will work in R

    rescale <- function(x) (x-min(x))/(max(x) - min(x)) * 100
    rescale(x)
    

    Or, you could use other transformations. For example, the logit transform was mentioned by @ondrej

    plogis(x)*100
    

    or, other transforms:

    pnorm(x)*100
    pnorm(x, 0, 100) * 100
    punif(x, min(x), max(x))*100
    
  • Just to add to ttnphnss's answer, to implement this process in Python (for example), this function will do the trick:

    from __future__ import division
    
    def rescale(values, new_min = 0, new_max = 100):
        output = []
        old_min, old_max = min(values), max(values)
    
        for v in values:
            new_v = (new_max - new_min) / (old_max - old_min) * (v - old_min) + new_min
            output.append(new_v)
    
        return output
    
    print rescale([1, 2, 3, 4, 5])
    # [0.0, 25.0, 50.0, 75.0, 100.0]
    

    Thanks, does this formula also apply on negative values?? for example, if my original variable ranges from -10 to 10 .

    Yes - it works for all values - for example, `print rescale([-10, -9, -5, 2, 6])` `# [0.0, 6.25, 31.25, 75.0, 100.0]`

  • I suggest not to bind the index to 0-100 interval, as it does not improve interpretation, but rather makes it more difficult. If the index constituents can be negative, then it is possible that the index becomes negative, and it reflects what's going on with constituents better than some low value in 0-100 range, in my opinion.

  • For R with standard packages loaded, you may just use scale() from 'base' package:

    x=c(2,4,8,16)
    x.scaled = scale(x,FALSE,max(x))  # divide each value in x by max(x)
    x.scaled = as.vector(x.scaled) 
    

    use 'as.vector()' to retrieve the scaled x as vector.

    Since the original values can be negative, dividing by the largest value won't be sufficient. Please consider the question more carefully, and --- given David and Mikko have already posted answers that take that aspect into account -- to get thumbs to go up, you'd generally need to contribute something their answers did not.

    You are absolutely right, sorry for that.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM