410
$\begingroup$

I am lost in normalizing, could anyone guide me please.

I have a minimum and maximum values, say -23.89 and 7.54990767, respectively.

If I get a value of 5.6878 how can I scale this value on a scale of 0 to 1.

$\endgroup$
4
  • 19
    $\begingroup$ is this the way =(value-min)/(max-min) $\endgroup$
    – Angelo
    Commented Sep 23, 2013 at 15:31
  • 3
    $\begingroup$ It may help you to read this thread: how-to-verify-a-distribution-is-normalized. If that answers your question, you can delete this Q; if not, edit your Q to specify what you still don't understand. $\endgroup$ Commented Sep 23, 2013 at 16:00
  • 2
    $\begingroup$ Explanation of protection: This question is attracting extra answers containing code solutions only. While these may be interesting or useful to some readers, it's not an aim of CV to provide repositories of code solutions. $\endgroup$
    – Nick Cox
    Commented May 27, 2015 at 8:42
  • 2
    $\begingroup$ the solutions provided consider a linear contrast value - would you like a different normalization, for instance one that achieve an uniform probability for the output? $\endgroup$
    – meduz
    Commented May 21, 2018 at 16:31

7 Answers 7

467
$\begingroup$

If you want to normalize your data, you can do so as you suggest and simply calculate the following:

$$z_i=\frac{x_i-\min(x)}{\max(x)-\min(x)}$$

where $x=(x_1,...,x_n)$ and $z_i$ is now your $i^{th}$ normalized data. As a proof of concept (although you did not ask for it) here is some R code and accompanying graph to illustrate this point:

enter image description here

# Example Data
x = sample(-100:100, 50)

#Normalized Data
normalized = (x-min(x))/(max(x)-min(x))

# Histogram of example data and normalized data
par(mfrow=c(1,2))
hist(x,          breaks=10, xlab="Data",            col="lightblue", main="")
hist(normalized, breaks=10, xlab="Normalized Data", col="lightblue", main="")
$\endgroup$
10
  • 25
    $\begingroup$ I only wonder how the two quite different-looking histograms do illustrate the point of your (correct) answer? $\endgroup$
    – ttnphns
    Commented Sep 23, 2013 at 16:21
  • 22
    $\begingroup$ @ttnphns They look only different due to the binning of the histograms. My point however was to show that the original values lived between -100 to 100 and now after normalization they live between 0 and 1. I could have used a different graph to show this I suppose or just summary statistics. $\endgroup$
    – user25658
    Commented Sep 23, 2013 at 16:23
  • 28
    $\begingroup$ The gentle nudge by @ttnphns was meant to encourage you not only to use a less complicated means of illustrating a (simple) idea, but also (I suspect) as a hint that a more directly relevant illustration might be beneficial here. You could do both by finding a more straightforward way to graph the transformation when it is applied to the min and max actually supplied by the O.P. $\endgroup$
    – whuber
    Commented Sep 23, 2013 at 17:12
  • 2
    $\begingroup$ Is there a way to "normalize" to custom range instead of 0-1? $\endgroup$ Commented Oct 25, 2016 at 11:46
  • 2
    $\begingroup$ @JohnDemetriou May not be the cleanest solution, but you can scale the normalized values to do that. If you want for example range of 0-100, you just multiply each number by 100. If you want range that is not beginning with 0, like 10-100, you would do it by scaling by the MAX-MIN and then to the values you get from that just adding the MIN. So scale by 90, then add 10. That should be enough for most of the custom ranges you may want. $\endgroup$ Commented Oct 29, 2017 at 18:54
74
$\begingroup$

The general one-line formula to linearly rescale data values having observed min and max into a new arbitrary range min' to max' is

  newvalue= (max'-min')/(max-min)*(value-max)+max'
  or
  newvalue= (max'-min')/(max-min)*(value-min)+min'.
$\endgroup$
6
  • 13
    $\begingroup$ This is correct, but not efficient. It is a linear transformation, so you would precalculate a and b constants, and then just apply newvalue = a * value + b. a = (max'-min')/(max-min) and b = max - a * max $\endgroup$ Commented Sep 23, 2013 at 19:18
  • 4
    $\begingroup$ Do you know how to cite this? I mean, is there an "original" reference somewhere? $\endgroup$
    – Trefex
    Commented May 11, 2014 at 20:18
  • 6
    $\begingroup$ @MarkLakata Slight (typo?) correction: b = max' - a * max or b = min' - (a * min) $\endgroup$
    – Nick
    Commented Dec 29, 2014 at 18:09
  • $\begingroup$ @Nick - yes. I'm missing a ' $\endgroup$ Commented Dec 30, 2014 at 5:33
  • $\begingroup$ Can you please compare your normalisation here se.mathworks.com/matlabcentral/answers/… i.e. the equation u = -1 + 2.*(u - min(u))./(max(u) - min(u));. $\endgroup$ Commented Oct 24, 2016 at 21:41
22
$\begingroup$

Here is my PHP implementation for normalisation:

function normalize($value, $min, $max) {
	$normalized = ($value - $min) / ($max - $min);
	return $normalized;
}

But while I was building my own artificial neural networks, I needed to transform the normalized output back to the original data to get good readable output for the graph.

function denormalize($normalized, $min, $max) {
	$denormalized = ($normalized * ($max - $min) + $min);
	return $denormalized;
}

$int = 12;
$max = 20;
$min = 10;

$normalized = normalize($int, $min, $max); // 0.2
$denormalized = denormalize($normalized, $min, $max); //12

Denormalisation uses the following formula:

$x (\text{max} - \text{min}) + \text{min}$

$\endgroup$
5
  • 2
    $\begingroup$ I don't think, that this is the only difference. In my code, I also showed, how to return a normalized value to the value it was before normalisation. I think, that makes it worth this answer. $\endgroup$
    – jankal
    Commented May 27, 2015 at 9:02
  • 3
    $\begingroup$ It's still true that you post only code: I think you need to emphasise any supposedly special virtues of code in commentary, as otherwise readers have to read the code to see what they are. Presumably inverting the scaling is of use only when (a) the original values have been overwritten but (b) the user has prudently remembered to save the minimum and maximum. My wider point, as commented above, is that CV does not aim to be a repository of code examples. $\endgroup$
    – Nick Cox
    Commented May 27, 2015 at 9:10
  • $\begingroup$ There are some problems, whre you need to restore the value: Nueral Networks for example... But you're right, in manner of data analysis, this answer is very bad. $\endgroup$
    – jankal
    Commented May 27, 2015 at 9:25
  • 4
    $\begingroup$ @NickCox I found his answer to be more satisfactory than the accepted one. $\endgroup$ Commented Aug 30, 2015 at 18:40
  • 1
    $\begingroup$ @Karl Morrison You can and should upvote it then. But code only answers strictly remain off-topic here. $\endgroup$
    – Nick Cox
    Commented Aug 31, 2015 at 9:08
10
$\begingroup$

Division by zero

One thing to keep in mind is that max - min could equal zero. In this case, you would not want to perform that division.

The case where this would happen is when all values in the list you're trying to normalize are the same. To normalize such a list, each item would be 1 / length.

// JavaScript
function normalize(list) {
   var minMax = list.reduce((acc, value) => {
      if (value < acc.min) {
         acc.min = value;
      }

      if (value > acc.max) {
         acc.max = value;
      }

      return acc;
   }, {min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY});

   return list.map(value => {
      // Verify that you're not about to divide by zero
      if (minMax.max === minMax.min) {
         return 1 / list.length
      }

      var diff = minMax.max - minMax.min;
      return (value - minMax.min) / diff;
   });
}

Example:

normalize([3, 3, 3, 3]); // output => [0.25, 0.25, 0.25, 0.25]
$\endgroup$
5
  • $\begingroup$ This is a rescaling to a sum 1, not to a range 0-1. I just think the answer is off-topic therefore. $\endgroup$
    – ttnphns
    Commented Oct 4, 2017 at 17:31
  • $\begingroup$ Not so. normalize([12, 20, 10]) outputs [0.2, 1.0, 0.0], which is the same you would get with (val - min) / (max - min). $\endgroup$ Commented Jan 16, 2019 at 15:23
  • 1
    $\begingroup$ @rodrigo-silveira I don't see why the all 0.25 output. Isn't it better all 0.5? All items are equal, so should be kept centered in the interval. $\endgroup$ Commented Apr 2, 2019 at 14:56
  • 1
    $\begingroup$ If the variable is a constant, it won't be much use either as an outcome or as a a predictor. Either way, you should not want to standardize it. I suppose the main message here is "Watch out if you try to standardize every variable in sight, as your code will give puzzling results or even fail without a trap for this case", $\endgroup$
    – Nick Cox
    Commented May 16, 2020 at 8:27
  • $\begingroup$ "will" in previous should be "may". $\endgroup$
    – Nick Cox
    Commented May 16, 2020 at 8:36
4
$\begingroup$

Try this. It is consistent with the function scale

normalize <- function(x) { 
  x <- as.matrix(x)
  minAttr=apply(x, 2, min)
  maxAttr=apply(x, 2, max)
  x <- sweep(x, 2, minAttr, FUN="-") 
  x=sweep(x, 2,  maxAttr-minAttr, "/") 
  attr(x, 'normalized:min') = minAttr
  attr(x, 'normalized:max') = maxAttr
  return (x)
} 
$\endgroup$
0
2
$\begingroup$

The answer is right but I have a suggestion, what if your training data face some number out of range? you could use the squashing technique. it will be guaranteed never to go out of range. rather than this

enter image description here

I recommend using this

enter image description here

with squashing like this in min and max of the range

enter image description here

and the size of the expected out-of-range gap is directly proportional to the degree of confidence that there will be out-of-range values.

For more information, you can google: squashing the out-of-range numbers and refer to the data preparation book of "Dorian Pyle".

$\endgroup$
2
  • 7
    $\begingroup$ Please edit your answer to use capitalisation as conventional. Consistent lower case may seem amusing or efficient, but it is more difficult for almost everyone to read. $\endgroup$
    – Nick Cox
    Commented Sep 25, 2013 at 12:12
  • 7
    $\begingroup$ The illustrations do not adequately convey your answer. What exactly is a "squashing technique"? $\endgroup$
    – whuber
    Commented Sep 25, 2013 at 14:47
-2
$\begingroup$

Select a cumulative probability distribution F. Then F(x) is between 0 and 1 for every x.

$\endgroup$
1
  • 2
    $\begingroup$ Correct but not an answer to the question. In fact most recipes for the empirical CDF would map say data 1, 2, 3, 4, 5 to 0.2(0.2)1 or possibly 0(0.2)0.8 or just possibly 0.1(0.2)0.9, so you would hard put to it to justify this even as an oblique answer to this question where the limits 0 and 1 should be attained. $\endgroup$
    – Nick Cox
    Commented May 16, 2020 at 7:56

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