28
$\begingroup$

I am not really sure what this operation might be called, but I have some numbers, for example:

  • 40
  • 10

I need to format these numbers so that they form the sum 1, but they should keep their "weight".

In this specific case:

  • 40 would become 0.80
  • 10 would become 0.2

But if I have more values (like 40, 10, 25, 5 for example), I am really lost because I don't know the formula.

If anybody can help, could they please reply in words (for example: "Sum up all values then divide through...", and not in a formula? I am really not good at reading formulas at all.

$\endgroup$
3
  • $\begingroup$ how should $[40,10]$ become $[0.75,0.25]$? $\frac{40}{10} \neq \frac{0.75}{0.25}$ $\endgroup$ Jan 14, 2013 at 6:38
  • 5
    $\begingroup$ Shouldn't $[40,10]$ become $[0.8,0.2]$? Then it's easy - just divide each element by the sum. $\endgroup$ Jan 14, 2013 at 6:43
  • $\begingroup$ @Jan Dvorak Thank you very much!! Can you please set your reply as an answer? $\endgroup$
    – tmighty
    Jan 14, 2013 at 6:50

7 Answers 7

45
$\begingroup$

Why not just divide each number in your sample by the sum of all the numbers in your sample?

$\endgroup$
1
  • 10
    $\begingroup$ What if the sum is 0? $\endgroup$
    – Asclepius
    Oct 16, 2018 at 3:04
15
$\begingroup$

The answers provided here won't work in cases where the set contains negative numbers.

The function you're looking for is called the softmax function. The softmax function is often used in the final layer of a neural network-based classifier. Softmax is defined as:

$$f_i(x) = \frac{e^{x_i}}{\sum_j e^{x_j}}$$

$\endgroup$
1
  • 6
    $\begingroup$ This does not maintain the relative spacing of the values. Small values become less import -> larger values are relatively larger after the softmax. OP wanted their "weights" to remain unchanged. $\endgroup$
    – n1k31t4
    Apr 16, 2020 at 20:22
12
$\begingroup$

I'm currently learning probability from an online course.

It's teaching me to use this amazingly simple method, and so far it has worked flawlessly!

Where e is an element in the list of numbers to be normalized:

Calculate a normalizer (multiplier) like so:

normalizer = 1 / (e1 + e2 + e3)

Next, multiply the normalizer to every element in the list:

((e1 * normalizer) + (e2 * normalizer) + .... + (en * normalizer) ) == 1.0

... and they will add up to 1.0.

So taking your example of numbers 10 and 40:

normalizer = 1 / (10 + 40) = 0.02
(10 * 0.02) = 0.2
(40 * 0.02) = 0.8
(0.2 + 0.8) = 1.0

Hence we get our 1.0.

I've gone ahead and written a simple Python script that you can run on almost any Python interpreter and play around with the parameters and test the results.

# python script
import random as rnd

# number of items in list, change this to as huge a list as you want
itemsInList = 5 

# specify min and max value bounds for randomly generated values
# change these to play around with different value ranges
minVal = 8
maxVal = 20

# creates a list of random values between minVal and maxVal, and sort them
numList = sorted( [rnd.randint(minVal, maxVal) for x in range(itemsInList)] )
print ('initial list is\n{}\n'.format(numList))

# calculate the normalizer, using: (1 / (sum_of_all_items_in_list))
normalizer = 1 / float( sum(numList) )

# multiply each item by the normalizer
numListNormalized = [x * normalizer for x in numList]
print('Normalized list is\n{}\n'.format(numListNormalized))

print('Sum of all items in numListNormalized is {}'.format(sum(numListNormalized)))

Running the code gives this sample output:

initial list is
[9, 12, 15, 16, 19]

Normalized list is
[0.1267605633802817, 0.16901408450704225, 0.2112676056338028, 0.22535211267605634, 0.26760563380281693]

Sum of all items in numListNormalized is 1.0

I hope this helps!

$\endgroup$
4
  • 2
    $\begingroup$ The best answer here, according to my understanding of the question. Works with negative numbers too 👍Also, you can "rescale" you array to maintain any sum, not only 1. Then the normalizer should divide the target sum value instead of 1. $\endgroup$ May 24, 2020 at 13:10
  • $\begingroup$ Excellent. How would I proceed if I need to split 1 into weighted parts? The reverse of this approach? If I need 2 parts, I would need 0.8 and 0.2. If I need 3 parts, 0.6, 0.3, 0.1. And so on. How would I approach this problem? $\endgroup$ Mar 15, 2021 at 5:43
  • 1
    $\begingroup$ e1 + e2 + e3 can sum to 0, then a division by zero would happen. $\endgroup$
    – fjsj
    Apr 23, 2021 at 15:33
  • $\begingroup$ Thank you, this is definitely the best answer. Note that if you need to normalise to some other number than 1 (say, you want to balance percentages to add up to 100) you can simply do normalizer = 100 / (e1 + e2 + e3). This scales to any number of es. $\endgroup$
    – theberzi
    Aug 31 at 19:18
11
$\begingroup$

From the text description, it seems this is what you want:

  • calculate the sum of all elements
  • divide each element by the sum

Note that, however, then your example $[40, 10]$ normalises as $[0.8, 0.2]$, not $[0.75,0.25]$. The latter doesn't preserve the ratio of both elements.

$\endgroup$
1
$\begingroup$

My take on the problem. First, in order to get rid of negative numbers, subtract all values in the original vector $\vec{x}$ by the minimum value in it: $\vec{u}=\vec{x}-\text{min}(\vec{x})$. This will ensure the minimum value in $\vec{u}$ will be 0. Then, the final "normalized" values between 0 and 1 are given by $$z_i = \frac{\vec{u}_i}{\sum_{j \in \vec{u}} \vec{u}_{j}}.$$

Edit: as pointed out in the comments, subtracting the minimum value of $\vec{x}$ from all values in $\vec{x}$ should only be done if at least one of the values in $\vec{x}$ is negative. After this step, the sum of the values in the final vector $\vec{z}$ will be 1.

What it means to calculate ratios involving negative values is open to interpretation. Maybe it's a closer behavior to that of the softmax function in machine learning, as it makes all values positive and sum to 1.

$\endgroup$
4
  • 1
    $\begingroup$ Why are you subtracting the minimal value? In the example provided, it would turn the 10 to 0 but the example says that it should turn to 0.2. $\endgroup$
    – Hume2
    May 15, 2020 at 11:48
  • $\begingroup$ You're right. I'll have a go at this again later. $\endgroup$ May 15, 2020 at 16:27
  • $\begingroup$ @Hume2 I just realized that subtracting the minimal value, when there is at least one negative value in the vector, may solve the problem of having negative values in the original vector, as after this, dividing all values by their sum still results in a kind of vector of ratios, in which their sum is 1. I just don't know if there is an interpretation to that, as we're dealing with ratios involving negative numbers. It should not be done if values are greater than or equal to 0. $\endgroup$ May 17, 2020 at 19:32
  • $\begingroup$ If the sum is zero, the "weight" isn't defined either. And when there are negative numbers but the sum is still nonzero, I don't see why the "weight" should be defined differently. $\endgroup$
    – Hume2
    May 18, 2020 at 5:12
0
$\begingroup$

Divide $100$ by the sum which is $80$ to get $1.25$. Then you multiply the the terms and use simple proportion where $80*1.25=100$ is proportional to one. You will get answers like $05,0.125,0.3125$ and $0.0625$.

$\endgroup$
-1
$\begingroup$

Just divide all the numbers through by 50. Should normalise it to the scale you want 0 - 1. For example: 40/50 = 0.8 25/50 = 0.5 5/50 = 0.1

etc.

I think you get the idea!

$\endgroup$
1
  • 1
    $\begingroup$ This doesn't normalise the sum in 1-0 $\endgroup$
    – TMrtSmith
    Nov 15, 2018 at 15:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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